@exxili/capacitor-nfc 0.0.11 → 0.0.13

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/plugin.js CHANGED
@@ -1,17 +1,60 @@
1
1
  var capacitorNFC = (function (exports, core) {
2
2
  'use strict';
3
3
 
4
+ var _a, _b;
4
5
  const NFCPlug = core.registerPlugin('NFC', {
5
- web: () => Promise.resolve().then(function () { return web; }).then(m => new m.NFCWeb()),
6
+ // Explicit .js extension required under node16/nodenext module resolution for emitted ES modules.
7
+ web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.NFCWeb()),
6
8
  });
7
9
  const NFC = {
8
10
  isSupported: NFCPlug.isSupported.bind(NFCPlug),
9
- startScan: NFCPlug.startScan.bind(NFCPlug),
11
+ startScan: (options) => {
12
+ const normalizedOptions = {};
13
+ if (options) {
14
+ for (const [key, value] of Object.entries(options)) {
15
+ if (value !== undefined && value !== null) {
16
+ normalizedOptions[key] = value;
17
+ }
18
+ }
19
+ }
20
+ return NFCPlug.startScan(normalizedOptions);
21
+ },
22
+ cancelScan: (_b = (_a = NFCPlug.cancelScan) === null || _a === void 0 ? void 0 : _a.bind(NFCPlug)) !== null && _b !== void 0 ? _b : (async () => {
23
+ /* Android no-op */
24
+ }),
10
25
  cancelWriteAndroid: NFCPlug.cancelWriteAndroid.bind(NFCPlug),
11
- onRead: (func) => NFC.wrapperListeners.push(func),
12
- onWrite: (func) => NFCPlug.addListener(`nfcWriteSuccess`, func),
26
+ onRead: (func) => {
27
+ NFC.wrapperListeners.push(func);
28
+ // Return unsubscribe function
29
+ return () => {
30
+ NFC.wrapperListeners = NFC.wrapperListeners.filter((l) => l !== func);
31
+ };
32
+ },
33
+ onWrite: (func) => {
34
+ let handle;
35
+ NFCPlug.addListener(`nfcWriteSuccess`, func).then((h) => (handle = h));
36
+ return () => {
37
+ var _a;
38
+ try {
39
+ (_a = handle === null || handle === void 0 ? void 0 : handle.remove) === null || _a === void 0 ? void 0 : _a.call(handle);
40
+ }
41
+ catch (_b) {
42
+ /* empty */
43
+ }
44
+ };
45
+ },
13
46
  onError: (errorFn) => {
14
- NFCPlug.addListener(`nfcError`, errorFn);
47
+ let handle;
48
+ NFCPlug.addListener(`nfcError`, errorFn).then((h) => (handle = h));
49
+ return () => {
50
+ var _a;
51
+ try {
52
+ (_a = handle === null || handle === void 0 ? void 0 : handle.remove) === null || _a === void 0 ? void 0 : _a.call(handle);
53
+ }
54
+ catch (_b) {
55
+ /* empty */
56
+ }
57
+ };
15
58
  },
16
59
  removeAllListeners: (eventName) => {
17
60
  NFC.wrapperListeners = [];
@@ -20,63 +63,201 @@ var capacitorNFC = (function (exports, core) {
20
63
  wrapperListeners: [],
21
64
  async writeNDEF(options) {
22
65
  var _a;
66
+ // Helper encoders for well-known record types (only applied to string payloads)
67
+ const buildTextPayload = (text, lang = 'en') => {
68
+ const langBytes = Array.from(new TextEncoder().encode(lang));
69
+ const textBytes = Array.from(new TextEncoder().encode(text));
70
+ const status = langBytes.length & 0x3f; // UTF-8 encoding, language length (<= 63)
71
+ return [status, ...langBytes, ...textBytes];
72
+ };
73
+ const buildUriPayload = (uri, prefixCode = 0x00) => {
74
+ const uriBytes = Array.from(new TextEncoder().encode(uri));
75
+ return [prefixCode, ...uriBytes];
76
+ };
77
+ const recordsArray = (_a = options === null || options === void 0 ? void 0 : options.records) !== null && _a !== void 0 ? _a : [];
78
+ if (recordsArray.length === 0)
79
+ throw new Error('At least one NDEF record is required');
80
+ const isRawMode = (options === null || options === void 0 ? void 0 : options.rawMode) === true;
23
81
  const ndefMessage = {
24
- records: (_a = options === null || options === void 0 ? void 0 : options.records.map((record) => {
25
- const payload = typeof record.payload === 'string'
26
- ? Array.from(new TextEncoder().encode(record.payload))
27
- : Array.isArray(record.payload)
28
- ? record.payload
29
- : record.payload instanceof Uint8Array
30
- ? Array.from(record.payload)
31
- : null;
82
+ records: recordsArray.map((record) => {
83
+ let payload = null;
84
+ if (typeof record.payload === 'string') {
85
+ if (isRawMode) {
86
+ // Raw mode: write string payloads as UTF-8 bytes without any framing
87
+ payload = Array.from(new TextEncoder().encode(record.payload));
88
+ }
89
+ else {
90
+ // Apply spec-compliant formatting only for Well Known Text (T) & URI (U) types.
91
+ if (record.type === 'T') {
92
+ payload = buildTextPayload(record.payload);
93
+ }
94
+ else if (record.type === 'U') {
95
+ payload = buildUriPayload(record.payload);
96
+ }
97
+ else {
98
+ // Generic string: raw UTF-8 bytes (no extra framing)
99
+ payload = Array.from(new TextEncoder().encode(record.payload));
100
+ }
101
+ }
102
+ }
103
+ else if (Array.isArray(record.payload)) {
104
+ // Assume already raw bytes; do NOT modify
105
+ payload = record.payload;
106
+ }
107
+ else if (record.payload instanceof Uint8Array) {
108
+ payload = Array.from(record.payload);
109
+ }
32
110
  if (!payload)
33
- throw 'Unsupported payload type';
34
- return {
35
- type: record.type,
36
- payload,
37
- };
38
- })) !== null && _a !== void 0 ? _a : [],
111
+ throw new Error('Unsupported payload type');
112
+ return { type: record.type, payload };
113
+ }),
39
114
  };
40
115
  await NFCPlug.writeNDEF(ndefMessage);
41
116
  },
42
117
  };
43
- const decodeBase64 = (base64Payload) => {
44
- return atob(base64Payload)
45
- .split('')
46
- .map((char) => char.charCodeAt(0));
118
+ // Decode a base64 string into a Uint8Array (browser-safe). Existing code used atob already.
119
+ const decodeBase64ToBytes = (base64Payload) => {
120
+ const bin = atob(base64Payload);
121
+ const out = new Uint8Array(bin.length);
122
+ for (let i = 0; i < bin.length; i++)
123
+ out[i] = bin.charCodeAt(i);
124
+ return out;
125
+ };
126
+ // Parse NFC Forum "Text" (Well Known 'T') records according to spec.
127
+ const decodeTextRecord = (bytes) => {
128
+ if (bytes.length === 0)
129
+ return '';
130
+ const status = bytes[0];
131
+ const isUTF16 = (status & 0x80) !== 0; // Bit 7 indicates encoding
132
+ const langLength = status & 0x3f; // Bits 0-5 language code length
133
+ if (1 + langLength > bytes.length)
134
+ return ''; // Corrupt
135
+ const textBytes = bytes.slice(1 + langLength);
136
+ try {
137
+ const decoder = new TextDecoder(isUTF16 ? 'utf-16' : 'utf-8');
138
+ return decoder.decode(textBytes);
139
+ }
140
+ catch (_a) {
141
+ // Fallback: naive ASCII
142
+ return Array.from(textBytes)
143
+ .map((b) => String.fromCharCode(b))
144
+ .join('');
145
+ }
146
+ };
147
+ // Basic URI prefix table for Well Known 'U' records (optional convenience)
148
+ const URI_PREFIX = [
149
+ '',
150
+ 'http://www.',
151
+ 'https://www.',
152
+ 'http://',
153
+ 'https://',
154
+ 'tel:',
155
+ 'mailto:',
156
+ 'ftp://anonymous:anonymous@',
157
+ 'ftp://ftp.',
158
+ 'ftps://',
159
+ 'sftp://',
160
+ 'smb://',
161
+ 'nfs://',
162
+ 'ftp://',
163
+ 'dav://',
164
+ 'news:',
165
+ 'telnet://',
166
+ 'imap:',
167
+ 'rtsp://',
168
+ 'urn:',
169
+ 'pop:',
170
+ 'sip:',
171
+ 'sips:',
172
+ 'tftp:',
173
+ 'btspp://',
174
+ 'btl2cap://',
175
+ 'btgoep://',
176
+ 'tcpobex://',
177
+ 'irdaobex://',
178
+ 'file://',
179
+ 'urn:epc:id:',
180
+ 'urn:epc:tag:',
181
+ 'urn:epc:pat:',
182
+ 'urn:epc:raw:',
183
+ 'urn:epc:',
184
+ 'urn:nfc:',
185
+ ];
186
+ const decodeUriRecord = (bytes) => {
187
+ if (bytes.length === 0)
188
+ return '';
189
+ const prefixIndex = bytes[0];
190
+ const prefix = URI_PREFIX[prefixIndex] || '';
191
+ const remainder = bytes.slice(1);
192
+ try {
193
+ return prefix + new TextDecoder('utf-8').decode(remainder);
194
+ }
195
+ catch (_a) {
196
+ return (prefix +
197
+ Array.from(remainder)
198
+ .map((b) => String.fromCharCode(b))
199
+ .join(''));
200
+ }
201
+ };
202
+ const toStringPayload = (recordType, bytes) => {
203
+ // Well Known Text
204
+ if (recordType === 'T')
205
+ return decodeTextRecord(bytes);
206
+ // Well Known URI
207
+ if (recordType === 'U')
208
+ return decodeUriRecord(bytes);
209
+ // Default: attempt UTF-8 decode
210
+ try {
211
+ return new TextDecoder('utf-8').decode(bytes);
212
+ }
213
+ catch (_a) {
214
+ return Array.from(bytes)
215
+ .map((c) => String.fromCharCode(c))
216
+ .join('');
217
+ }
47
218
  };
48
219
  const mapPayloadTo = (type, data) => {
49
220
  return {
50
- messages: data.messages.map(message => ({
51
- records: message.records.map(record => ({
52
- type: record.type,
53
- payload: type === "b64"
54
- ? record.payload
55
- : type === "string"
56
- ? decodeBase64(record.payload)
57
- : type === "uint8Array"
58
- ? new Uint8Array(decodeBase64(record.payload))
59
- : type === "numberArray"
60
- ? Array.from(decodeBase64(record.payload))
61
- : record.payload
62
- }))
63
- }))
221
+ messages: data.messages.map((message) => ({
222
+ records: message.records.map((record) => {
223
+ const bytes = decodeBase64ToBytes(record.payload);
224
+ let payload;
225
+ switch (type) {
226
+ case 'b64':
227
+ payload = record.payload; // original base64 string
228
+ break;
229
+ case 'uint8Array':
230
+ payload = bytes;
231
+ break;
232
+ case 'numberArray':
233
+ payload = Array.from(bytes);
234
+ break;
235
+ case 'string':
236
+ payload = toStringPayload(record.type, bytes);
237
+ break;
238
+ default:
239
+ payload = record.payload;
240
+ }
241
+ return { type: record.type, payload };
242
+ }),
243
+ })),
244
+ tagInfo: data.tagInfo, // Include tag information
64
245
  };
65
246
  };
66
- NFCPlug.addListener(`nfcTag`, data => {
247
+ NFCPlug.addListener(`nfcTag`, (data) => {
67
248
  const wrappedData = {
68
249
  base64() {
69
- return mapPayloadTo("b64", data);
250
+ return mapPayloadTo('b64', data);
70
251
  },
71
252
  string() {
72
- return mapPayloadTo("string", data);
253
+ return mapPayloadTo('string', data);
73
254
  },
74
255
  uint8Array() {
75
- return mapPayloadTo("uint8Array", data);
256
+ return mapPayloadTo('uint8Array', data);
76
257
  },
77
258
  numberArray() {
78
- return mapPayloadTo("numberArray", data);
79
- }
259
+ return mapPayloadTo('numberArray', data);
260
+ },
80
261
  };
81
262
  for (const listener of NFC.wrapperListeners) {
82
263
  listener(wrappedData);
@@ -84,32 +265,20 @@ var capacitorNFC = (function (exports, core) {
84
265
  });
85
266
 
86
267
  class NFCWeb extends core.WebPlugin {
87
- constructor() {
88
- super(...arguments);
89
- this.wrapperListeners = [];
90
- }
91
- isSupported() {
92
- return Promise.resolve({ supported: false });
93
- }
94
- startScan() {
95
- return Promise.reject(new Error('NFC is not supported on web'));
96
- }
97
- cancelWriteAndroid() {
98
- return Promise.reject(new Error('NFC is not supported on web'));
268
+ async isSupported() {
269
+ return { supported: false };
99
270
  }
100
- writeNDEF() {
101
- return Promise.reject(new Error('NFC is not supported on web'));
271
+ async startScan(_options) {
272
+ throw new Error('NFC is not supported on web');
102
273
  }
103
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
104
- onRead(_func) {
105
- return Promise.reject(new Error('NFC is not supported on web'));
274
+ async cancelScan() {
275
+ throw new Error('NFC is not supported on web');
106
276
  }
107
- onWrite() {
108
- return Promise.reject(new Error('NFC is not supported on web'));
277
+ async cancelWriteAndroid() {
278
+ throw new Error('NFC is not supported on web');
109
279
  }
110
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
111
- onError(_errorFn) {
112
- return Promise.reject(new Error('NFC is not supported on web'));
280
+ async writeNDEF(_options) {
281
+ throw new Error('NFC is not supported on web');
113
282
  }
114
283
  }
115
284
 
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst NFCPlug = registerPlugin('NFC', {\n web: () => import('./web').then(m => new m.NFCWeb()),\n});\nexport * from './definitions';\nexport const NFC = {\n isSupported: NFCPlug.isSupported.bind(NFCPlug),\n startScan: NFCPlug.startScan.bind(NFCPlug),\n cancelWriteAndroid: NFCPlug.cancelWriteAndroid.bind(NFCPlug),\n onRead: (func) => NFC.wrapperListeners.push(func),\n onWrite: (func) => NFCPlug.addListener(`nfcWriteSuccess`, func),\n onError: (errorFn) => {\n NFCPlug.addListener(`nfcError`, errorFn);\n },\n removeAllListeners: (eventName) => {\n NFC.wrapperListeners = [];\n return NFCPlug.removeAllListeners(eventName);\n },\n wrapperListeners: [],\n async writeNDEF(options) {\n var _a;\n const ndefMessage = {\n records: (_a = options === null || options === void 0 ? void 0 : options.records.map((record) => {\n const payload = typeof record.payload === 'string'\n ? Array.from(new TextEncoder().encode(record.payload))\n : Array.isArray(record.payload)\n ? record.payload\n : record.payload instanceof Uint8Array\n ? Array.from(record.payload)\n : null;\n if (!payload)\n throw 'Unsupported payload type';\n return {\n type: record.type,\n payload,\n };\n })) !== null && _a !== void 0 ? _a : [],\n };\n await NFCPlug.writeNDEF(ndefMessage);\n },\n};\nconst decodeBase64 = (base64Payload) => {\n return atob(base64Payload)\n .split('')\n .map((char) => char.charCodeAt(0));\n};\nconst mapPayloadTo = (type, data) => {\n return {\n messages: data.messages.map(message => ({\n records: message.records.map(record => ({\n type: record.type,\n payload: type === \"b64\"\n ? record.payload\n : type === \"string\"\n ? decodeBase64(record.payload)\n : type === \"uint8Array\"\n ? new Uint8Array(decodeBase64(record.payload))\n : type === \"numberArray\"\n ? Array.from(decodeBase64(record.payload))\n : record.payload\n }))\n }))\n };\n};\nNFCPlug.addListener(`nfcTag`, data => {\n const wrappedData = {\n base64() {\n return mapPayloadTo(\"b64\", data);\n },\n string() {\n return mapPayloadTo(\"string\", data);\n },\n uint8Array() {\n return mapPayloadTo(\"uint8Array\", data);\n },\n numberArray() {\n return mapPayloadTo(\"numberArray\", data);\n }\n };\n for (const listener of NFC.wrapperListeners) {\n listener(wrappedData);\n }\n});\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class NFCWeb extends WebPlugin {\n constructor() {\n super(...arguments);\n this.wrapperListeners = [];\n }\n isSupported() {\n return Promise.resolve({ supported: false });\n }\n startScan() {\n return Promise.reject(new Error('NFC is not supported on web'));\n }\n cancelWriteAndroid() {\n return Promise.reject(new Error('NFC is not supported on web'));\n }\n writeNDEF() {\n return Promise.reject(new Error('NFC is not supported on web'));\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onRead(_func) {\n return Promise.reject(new Error('NFC is not supported on web'));\n }\n onWrite() {\n return Promise.reject(new Error('NFC is not supported on web'));\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n onError(_errorFn) {\n return Promise.reject(new Error('NFC is not supported on web'));\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["var _a, _b;\nimport { registerPlugin } from '@capacitor/core';\nconst NFCPlug = registerPlugin('NFC', {\n // Explicit .js extension required under node16/nodenext module resolution for emitted ES modules.\n web: () => import('./web.js').then((m) => new m.NFCWeb()),\n});\nexport * from './definitions.js';\nexport const NFC = {\n isSupported: NFCPlug.isSupported.bind(NFCPlug),\n startScan: (options) => {\n const normalizedOptions = {};\n if (options) {\n for (const [key, value] of Object.entries(options)) {\n if (value !== undefined && value !== null) {\n normalizedOptions[key] = value;\n }\n }\n }\n return NFCPlug.startScan(normalizedOptions);\n },\n cancelScan: (_b = (_a = NFCPlug.cancelScan) === null || _a === void 0 ? void 0 : _a.bind(NFCPlug)) !== null && _b !== void 0 ? _b : (async () => {\n /* Android no-op */\n }),\n cancelWriteAndroid: NFCPlug.cancelWriteAndroid.bind(NFCPlug),\n onRead: (func) => {\n NFC.wrapperListeners.push(func);\n // Return unsubscribe function\n return () => {\n NFC.wrapperListeners = NFC.wrapperListeners.filter((l) => l !== func);\n };\n },\n onWrite: (func) => {\n let handle;\n NFCPlug.addListener(`nfcWriteSuccess`, func).then((h) => (handle = h));\n return () => {\n var _a;\n try {\n (_a = handle === null || handle === void 0 ? void 0 : handle.remove) === null || _a === void 0 ? void 0 : _a.call(handle);\n }\n catch (_b) {\n /* empty */\n }\n };\n },\n onError: (errorFn) => {\n let handle;\n NFCPlug.addListener(`nfcError`, errorFn).then((h) => (handle = h));\n return () => {\n var _a;\n try {\n (_a = handle === null || handle === void 0 ? void 0 : handle.remove) === null || _a === void 0 ? void 0 : _a.call(handle);\n }\n catch (_b) {\n /* empty */\n }\n };\n },\n removeAllListeners: (eventName) => {\n NFC.wrapperListeners = [];\n return NFCPlug.removeAllListeners(eventName);\n },\n wrapperListeners: [],\n async writeNDEF(options) {\n var _a;\n // Helper encoders for well-known record types (only applied to string payloads)\n const buildTextPayload = (text, lang = 'en') => {\n const langBytes = Array.from(new TextEncoder().encode(lang));\n const textBytes = Array.from(new TextEncoder().encode(text));\n const status = langBytes.length & 0x3f; // UTF-8 encoding, language length (<= 63)\n return [status, ...langBytes, ...textBytes];\n };\n const buildUriPayload = (uri, prefixCode = 0x00) => {\n const uriBytes = Array.from(new TextEncoder().encode(uri));\n return [prefixCode, ...uriBytes];\n };\n const recordsArray = (_a = options === null || options === void 0 ? void 0 : options.records) !== null && _a !== void 0 ? _a : [];\n if (recordsArray.length === 0)\n throw new Error('At least one NDEF record is required');\n const isRawMode = (options === null || options === void 0 ? void 0 : options.rawMode) === true;\n const ndefMessage = {\n records: recordsArray.map((record) => {\n let payload = null;\n if (typeof record.payload === 'string') {\n if (isRawMode) {\n // Raw mode: write string payloads as UTF-8 bytes without any framing\n payload = Array.from(new TextEncoder().encode(record.payload));\n }\n else {\n // Apply spec-compliant formatting only for Well Known Text (T) & URI (U) types.\n if (record.type === 'T') {\n payload = buildTextPayload(record.payload);\n }\n else if (record.type === 'U') {\n payload = buildUriPayload(record.payload);\n }\n else {\n // Generic string: raw UTF-8 bytes (no extra framing)\n payload = Array.from(new TextEncoder().encode(record.payload));\n }\n }\n }\n else if (Array.isArray(record.payload)) {\n // Assume already raw bytes; do NOT modify\n payload = record.payload;\n }\n else if (record.payload instanceof Uint8Array) {\n payload = Array.from(record.payload);\n }\n if (!payload)\n throw new Error('Unsupported payload type');\n return { type: record.type, payload };\n }),\n };\n await NFCPlug.writeNDEF(ndefMessage);\n },\n};\n// Decode a base64 string into a Uint8Array (browser-safe). Existing code used atob already.\nconst decodeBase64ToBytes = (base64Payload) => {\n const bin = atob(base64Payload);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++)\n out[i] = bin.charCodeAt(i);\n return out;\n};\n// Parse NFC Forum \"Text\" (Well Known 'T') records according to spec.\nconst decodeTextRecord = (bytes) => {\n if (bytes.length === 0)\n return '';\n const status = bytes[0];\n const isUTF16 = (status & 0x80) !== 0; // Bit 7 indicates encoding\n const langLength = status & 0x3f; // Bits 0-5 language code length\n if (1 + langLength > bytes.length)\n return ''; // Corrupt\n const textBytes = bytes.slice(1 + langLength);\n try {\n const decoder = new TextDecoder(isUTF16 ? 'utf-16' : 'utf-8');\n return decoder.decode(textBytes);\n }\n catch (_a) {\n // Fallback: naive ASCII\n return Array.from(textBytes)\n .map((b) => String.fromCharCode(b))\n .join('');\n }\n};\n// Basic URI prefix table for Well Known 'U' records (optional convenience)\nconst URI_PREFIX = [\n '',\n 'http://www.',\n 'https://www.',\n 'http://',\n 'https://',\n 'tel:',\n 'mailto:',\n 'ftp://anonymous:anonymous@',\n 'ftp://ftp.',\n 'ftps://',\n 'sftp://',\n 'smb://',\n 'nfs://',\n 'ftp://',\n 'dav://',\n 'news:',\n 'telnet://',\n 'imap:',\n 'rtsp://',\n 'urn:',\n 'pop:',\n 'sip:',\n 'sips:',\n 'tftp:',\n 'btspp://',\n 'btl2cap://',\n 'btgoep://',\n 'tcpobex://',\n 'irdaobex://',\n 'file://',\n 'urn:epc:id:',\n 'urn:epc:tag:',\n 'urn:epc:pat:',\n 'urn:epc:raw:',\n 'urn:epc:',\n 'urn:nfc:',\n];\nconst decodeUriRecord = (bytes) => {\n if (bytes.length === 0)\n return '';\n const prefixIndex = bytes[0];\n const prefix = URI_PREFIX[prefixIndex] || '';\n const remainder = bytes.slice(1);\n try {\n return prefix + new TextDecoder('utf-8').decode(remainder);\n }\n catch (_a) {\n return (prefix +\n Array.from(remainder)\n .map((b) => String.fromCharCode(b))\n .join(''));\n }\n};\nconst toStringPayload = (recordType, bytes) => {\n // Well Known Text\n if (recordType === 'T')\n return decodeTextRecord(bytes);\n // Well Known URI\n if (recordType === 'U')\n return decodeUriRecord(bytes);\n // Default: attempt UTF-8 decode\n try {\n return new TextDecoder('utf-8').decode(bytes);\n }\n catch (_a) {\n return Array.from(bytes)\n .map((c) => String.fromCharCode(c))\n .join('');\n }\n};\nconst mapPayloadTo = (type, data) => {\n return {\n messages: data.messages.map((message) => ({\n records: message.records.map((record) => {\n const bytes = decodeBase64ToBytes(record.payload);\n let payload;\n switch (type) {\n case 'b64':\n payload = record.payload; // original base64 string\n break;\n case 'uint8Array':\n payload = bytes;\n break;\n case 'numberArray':\n payload = Array.from(bytes);\n break;\n case 'string':\n payload = toStringPayload(record.type, bytes);\n break;\n default:\n payload = record.payload;\n }\n return { type: record.type, payload };\n }),\n })),\n tagInfo: data.tagInfo, // Include tag information\n };\n};\nNFCPlug.addListener(`nfcTag`, (data) => {\n const wrappedData = {\n base64() {\n return mapPayloadTo('b64', data);\n },\n string() {\n return mapPayloadTo('string', data);\n },\n uint8Array() {\n return mapPayloadTo('uint8Array', data);\n },\n numberArray() {\n return mapPayloadTo('numberArray', data);\n },\n };\n for (const listener of NFC.wrapperListeners) {\n listener(wrappedData);\n }\n});\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class NFCWeb extends WebPlugin {\n async isSupported() {\n return { supported: false };\n }\n async startScan(_options) {\n throw new Error('NFC is not supported on web');\n }\n async cancelScan() {\n throw new Error('NFC is not supported on web');\n }\n async cancelWriteAndroid() {\n throw new Error('NFC is not supported on web');\n }\n async writeNDEF(_options) {\n throw new Error('NFC is not supported on web');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
@@ -10,6 +10,7 @@ public class NFCPlugin: CAPPlugin, CAPBridgedPlugin {
10
10
  CAPPluginMethod(name: "isSupported", returnType: CAPPluginReturnPromise),
11
11
  CAPPluginMethod(name: "cancelWriteAndroid", returnType: CAPPluginReturnPromise),
12
12
  CAPPluginMethod(name: "startScan", returnType: CAPPluginReturnPromise),
13
+ CAPPluginMethod(name: "cancelScan", returnType: CAPPluginReturnPromise),
13
14
  CAPPluginMethod(name: "writeNDEF", returnType: CAPPluginReturnPromise)
14
15
  ]
15
16
 
@@ -26,24 +27,54 @@ public class NFCPlugin: CAPPlugin, CAPBridgedPlugin {
26
27
 
27
28
  @objc func startScan(_ call: CAPPluginCall) {
28
29
  print("startScan called")
29
- reader.onNDEFMessageReceived = { messages in
30
+ if let preferredMode = call.getString("mode") {
31
+ reader.setPreferredReaderMode(preferredMode)
32
+ } else if call.getBool("forceFull") == true {
33
+ reader.setPreferredReaderMode("full")
34
+ } else if call.getBool("forceCompat") == true {
35
+ reader.setPreferredReaderMode("compat")
36
+ } else if call.getBool("forceNDEF") == true {
37
+ reader.setPreferredReaderMode("ndef")
38
+ }
39
+ reader.onNDEFMessageReceived = { messages, tagInfo in
30
40
  var ndefMessages = [[String: Any]]()
31
- for message in messages {
32
- var records = [[String: Any]]()
33
- for record in message.records {
34
- let recordType = String(data: record.type, encoding: .utf8) ?? ""
35
- let payloadData = record.payload.base64EncodedString()
36
-
37
- records.append([
38
- "type": recordType,
41
+
42
+ if messages.isEmpty {
43
+ // If no NDEF messages but we have tag info, create a fallback record with the UID
44
+ if let tagInfo = tagInfo, let uid = tagInfo["uid"] as? String {
45
+ let payloadData = uid.data(using: .utf8)?.base64EncodedString() ?? ""
46
+ let records = [[
47
+ "type": "ID",
39
48
  "payload": payloadData
49
+ ]]
50
+ ndefMessages.append([
51
+ "records": records
52
+ ])
53
+ }
54
+ } else {
55
+ for message in messages {
56
+ var records = [[String: Any]]()
57
+ for record in message.records {
58
+ let recordType = String(data: record.type, encoding: .utf8) ?? ""
59
+ let payloadData = record.payload.base64EncodedString()
60
+
61
+ records.append([
62
+ "type": recordType,
63
+ "payload": payloadData
64
+ ])
65
+ }
66
+ ndefMessages.append([
67
+ "records": records
40
68
  ])
41
69
  }
42
- ndefMessages.append([
43
- "records": records
44
- ])
45
70
  }
46
- self.notifyListeners("nfcTag", data: ["messages": ndefMessages])
71
+
72
+ var response: [String: Any] = ["messages": ndefMessages]
73
+ if let tagInfo = tagInfo {
74
+ response["tagInfo"] = tagInfo
75
+ }
76
+
77
+ self.notifyListeners("nfcTag", data: response)
47
78
  }
48
79
 
49
80
  reader.onError = { error in
@@ -58,6 +89,11 @@ public class NFCPlugin: CAPPlugin, CAPBridgedPlugin {
58
89
  call.resolve()
59
90
  }
60
91
 
92
+ @objc func cancelScan(_ call: CAPPluginCall) {
93
+ reader.cancelScanning()
94
+ call.resolve()
95
+ }
96
+
61
97
  @objc func writeNDEF(_ call: CAPPluginCall) {
62
98
  print("writeNDEF called")
63
99
 
@@ -69,26 +105,43 @@ public class NFCPlugin: CAPPlugin, CAPBridgedPlugin {
69
105
  var ndefRecords = [NFCNDEFPayload]()
70
106
  for recordData in recordsData {
71
107
  guard let type = recordData["type"] as? String,
72
- let payload = recordData["payload"] as? [NSNumber],
73
- let typeData = type.data(using: .utf8)
108
+ let payload = recordData["payload"] as? [NSNumber]
74
109
  else {
75
110
  print("Skipping record due to missing or invalid record")
76
111
  continue
77
112
  }
78
-
113
+
79
114
  guard let payloadArray = payload as [NSNumber]? else {
80
115
  print("Skipping record due to missing or invalid 'payload' (expected array of numbers)")
81
116
  continue
82
117
  }
83
-
118
+
84
119
  var payloadBytes = [UInt8]()
85
120
  for number in payloadArray {
86
121
  payloadBytes.append(number.uint8Value)
87
122
  }
88
123
  let payloadData = Data(payloadBytes)
89
124
 
125
+ let format: NFCTypeNameFormat
126
+ let typeEncoding: String.Encoding
127
+ if type == "T" || type == "U" {
128
+ format = .nfcWellKnown
129
+ typeEncoding = .utf8
130
+ } else if type.contains("/") {
131
+ format = .media
132
+ typeEncoding = .ascii
133
+ } else {
134
+ format = .nfcExternal
135
+ typeEncoding = .utf8
136
+ }
137
+
138
+ guard let typeData = type.data(using: typeEncoding) else {
139
+ print("Skipping record due to unsupported type encoding")
140
+ continue
141
+ }
142
+
90
143
  let ndefRecord = NFCNDEFPayload(
91
- format: .nfcWellKnown,
144
+ format: format,
92
145
  type: typeData,
93
146
  identifier: Data(),
94
147
  payload: payloadData