@savers_app/react-native-sdk 1.2.0 → 1.2.1

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/README.md CHANGED
@@ -101,8 +101,8 @@ import { SaversAppSDK } from '@savers_app/react-native-sdk';
101
101
  SaversAppSDK.initialized({
102
102
  apiKey: 'YOUR_API_KEY',
103
103
  encryptionKey: 'BASE64_256_BIT_ENCRYPTION_KEY',
104
- pRefCode: 'YOUR_P_REF_CODE',
105
- authMode: 'PHONE', // or 'EMAIL' | 'USERNAME'
104
+ pRefCode: 'PROGRAM_REF_CODE',
105
+ authMode: 'CUSTOMER_SIGN_IN_UP_MODE' // 'EMAIL' | 'PHONE'
106
106
  });
107
107
  ```
108
108
 
@@ -4,7 +4,7 @@
4
4
  import { Linking } from 'react-native';
5
5
 
6
6
  // Utilities / Helpers
7
- import { isMapAppAvailable, isValidCoordinates } from "../../utils/validator.js";
7
+ import { isValidCoordinates } from "../../utils/validator.js";
8
8
 
9
9
  // Platform / Environment helpers
10
10
  import { isIOS } from "../../utils/platformManager.js";
@@ -13,14 +13,30 @@ export async function openMap(lat, lng, label) {
13
13
  throw new Error('INVALID_COORDINATES');
14
14
  }
15
15
  const iosUrl = `maps:0,0?q=${encodeURIComponent(label ?? '')}@${lat},${lng}`;
16
- const androidUrl = `geo:0,0?q=${lat},${lng}${label ? `(${encodeURIComponent(label)})` : ''}`;
17
- const deepLink = isIOS() ? iosUrl : androidUrl;
18
- const available = await isMapAppAvailable();
19
- if (available) {
20
- await Linking.openURL(deepLink);
16
+ if (isIOS()) {
17
+ try {
18
+ await Linking.openURL(iosUrl);
19
+ return;
20
+ } catch {}
21
+ const browserUrl = `https://maps.apple.com/?q=${encodeURIComponent(label ?? '')}&ll=${lat},${lng}`;
22
+ await Linking.openURL(browserUrl);
21
23
  return;
22
24
  }
23
- const browserUrl = isIOS() ? `https://maps.apple.com/?q=${encodeURIComponent(label ?? '')}&ll=${lat},${lng}` : `https://www.google.com/maps/search/?api=1&query=${lat},${lng}${label ? `&query_place_id=${encodeURIComponent(label)}` : ''}`;
25
+ const encLabel = label ? encodeURIComponent(label) : undefined;
26
+ const query = `${lat},${lng}${encLabel ? `(${encLabel})` : ''}`;
27
+ const candidates = [
28
+ // Prefer geo to show a pin at the destination (not navigation)
29
+ `geo:${lat},${lng}?q=${query}`, `geo:0,0?q=${query}`,
30
+ // Fallback to Google Maps custom scheme as a generic search/pin
31
+ `comgooglemaps://?q=${query}`];
32
+ for (const url of candidates) {
33
+ try {
34
+ await Linking.openURL(url);
35
+ return;
36
+ } catch {}
37
+ }
38
+ const browserQuery = label ? `${label} ${lat},${lng}` : `${lat},${lng}`;
39
+ const browserUrl = `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(browserQuery)}`;
24
40
  await Linking.openURL(browserUrl);
25
41
  }
26
42
  //# sourceMappingURL=openMap.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["Linking","isMapAppAvailable","isValidCoordinates","isIOS","openMap","lat","lng","label","Error","iosUrl","encodeURIComponent","androidUrl","deepLink","available","openURL","browserUrl"],"sourceRoot":"../../../../src","sources":["services/navigation/openMap.ts"],"mappings":";;AAAA;AACA,SAASA,OAAO,QAAQ,cAAc;;AAEtC;AACA,SAASC,iBAAiB,EAAEC,kBAAkB,QAAQ,0BAAuB;;AAE7E;AACA,SAASC,KAAK,QAAQ,gCAA6B;AAEnD,OAAO,eAAeC,OAAOA,CAC3BC,GAAW,EACXC,GAAW,EACXC,KAAc,EACC;EACf,IAAI,CAACL,kBAAkB,CAACG,GAAG,EAAEC,GAAG,CAAC,EAAE;IACjC,MAAM,IAAIE,KAAK,CAAC,qBAAqB,CAAC;EACxC;EAEA,MAAMC,MAAM,GAAG,cAAcC,kBAAkB,CAACH,KAAK,IAAI,EAAE,CAAC,IAAIF,GAAG,IAAIC,GAAG,EAAE;EAC5E,MAAMK,UAAU,GAAG,aAAaN,GAAG,IAAIC,GAAG,GACxCC,KAAK,GAAG,IAAIG,kBAAkB,CAACH,KAAK,CAAC,GAAG,GAAG,EAAE,EAC7C;EACF,MAAMK,QAAQ,GAAGT,KAAK,CAAC,CAAC,GAAGM,MAAM,GAAGE,UAAU;EAE9C,MAAME,SAAS,GAAG,MAAMZ,iBAAiB,CAAC,CAAC;EAC3C,IAAIY,SAAS,EAAE;IACb,MAAMb,OAAO,CAACc,OAAO,CAACF,QAAQ,CAAC;IAC/B;EACF;EAEA,MAAMG,UAAU,GAAGZ,KAAK,CAAC,CAAC,GACtB,6BAA6BO,kBAAkB,CAC7CH,KAAK,IAAI,EACX,CAAC,OAAOF,GAAG,IAAIC,GAAG,EAAE,GACpB,mDAAmDD,GAAG,IAAIC,GAAG,GAC3DC,KAAK,GAAG,mBAAmBG,kBAAkB,CAACH,KAAK,CAAC,EAAE,GAAG,EAAE,EAC3D;EACN,MAAMP,OAAO,CAACc,OAAO,CAACC,UAAU,CAAC;AACnC","ignoreList":[]}
1
+ {"version":3,"names":["Linking","isValidCoordinates","isIOS","openMap","lat","lng","label","Error","iosUrl","encodeURIComponent","openURL","browserUrl","encLabel","undefined","query","candidates","url","browserQuery"],"sourceRoot":"../../../../src","sources":["services/navigation/openMap.ts"],"mappings":";;AAAA;AACA,SAASA,OAAO,QAAQ,cAAc;;AAEtC;AACA,SAASC,kBAAkB,QAAQ,0BAAuB;;AAE1D;AACA,SAASC,KAAK,QAAQ,gCAA6B;AAEnD,OAAO,eAAeC,OAAOA,CAC3BC,GAAW,EACXC,GAAW,EACXC,KAAc,EACC;EACf,IAAI,CAACL,kBAAkB,CAACG,GAAG,EAAEC,GAAG,CAAC,EAAE;IACjC,MAAM,IAAIE,KAAK,CAAC,qBAAqB,CAAC;EACxC;EAEA,MAAMC,MAAM,GAAG,cAAcC,kBAAkB,CAACH,KAAK,IAAI,EAAE,CAAC,IAAIF,GAAG,IAAIC,GAAG,EAAE;EAE5E,IAAIH,KAAK,CAAC,CAAC,EAAE;IACX,IAAI;MACF,MAAMF,OAAO,CAACU,OAAO,CAACF,MAAM,CAAC;MAC7B;IACF,CAAC,CAAC,MAAM,CAAC;IACT,MAAMG,UAAU,GAAG,6BAA6BF,kBAAkB,CAChEH,KAAK,IAAI,EACX,CAAC,OAAOF,GAAG,IAAIC,GAAG,EAAE;IACpB,MAAML,OAAO,CAACU,OAAO,CAACC,UAAU,CAAC;IACjC;EACF;EAEA,MAAMC,QAAQ,GAAGN,KAAK,GAAGG,kBAAkB,CAACH,KAAK,CAAC,GAAGO,SAAS;EAC9D,MAAMC,KAAK,GAAG,GAAGV,GAAG,IAAIC,GAAG,GAAGO,QAAQ,GAAG,IAAIA,QAAQ,GAAG,GAAG,EAAE,EAAE;EAC/D,MAAMG,UAAU,GAAG;EACjB;EACA,OAAOX,GAAG,IAAIC,GAAG,MAAMS,KAAK,EAAE,EAC9B,aAAaA,KAAK,EAAE;EACpB;EACA,sBAAsBA,KAAK,EAAE,CAC9B;EACD,KAAK,MAAME,GAAG,IAAID,UAAU,EAAE;IAC5B,IAAI;MACF,MAAMf,OAAO,CAACU,OAAO,CAACM,GAAG,CAAC;MAC1B;IACF,CAAC,CAAC,MAAM,CAAC;EACX;EACA,MAAMC,YAAY,GAAGX,KAAK,GAAG,GAAGA,KAAK,IAAIF,GAAG,IAAIC,GAAG,EAAE,GAAG,GAAGD,GAAG,IAAIC,GAAG,EAAE;EACvE,MAAMM,UAAU,GAAG,mDAAmDF,kBAAkB,CACtFQ,YACF,CAAC,EAAE;EACH,MAAMjB,OAAO,CAACU,OAAO,CAACC,UAAU,CAAC;AACnC","ignoreList":[]}
@@ -1,7 +1,20 @@
1
1
  "use strict";
2
2
 
3
- // Third-party libraries
3
+ import { NativeModules } from 'react-native';
4
4
  import AesGcmCrypto from 'react-native-aes-gcm-crypto';
5
+
6
+ /**
7
+ * Ensure native module is installed & linked
8
+ */
9
+ function ensureAesAvailable() {
10
+ const nativeModule = NativeModules.AesGcmCrypto || NativeModules.RNAesGcmCrypto;
11
+ if (!AesGcmCrypto || !nativeModule) {
12
+ throw new Error('react-native-aes-gcm-crypto is not installed or linked correctly.\n\n' + 'Fix:\n' + '1. yarn add react-native-aes-gcm-crypto\n' + '2. cd ios && pod install\n' + '3. Rebuild the app\n');
13
+ }
14
+ if (typeof AesGcmCrypto.encrypt !== 'function') {
15
+ throw new Error('AES-GCM native functions unavailable. Please rebuild the app.');
16
+ }
17
+ }
5
18
  function isBase64(input) {
6
19
  return /^[A-Za-z0-9+/]+={0,2}$/.test(input);
7
20
  }
@@ -10,26 +23,33 @@ function base64ByteLength(b64) {
10
23
  return Math.floor(cleaned.length * 3 / 4);
11
24
  }
12
25
  export async function aesEncrypt(text, key) {
26
+ ensureAesAvailable();
13
27
  if (!isBase64(key) || base64ByteLength(key) !== 32) {
14
28
  throw new Error('Encryption key must be base64-encoded 32-byte (256-bit) value');
15
29
  }
16
- const {
17
- iv,
18
- tag,
19
- content
20
- } = await AesGcmCrypto.encrypt(text, false, key);
21
- return base64Encrypt(`${iv}:${content}:${tag}`);
30
+ try {
31
+ const {
32
+ iv,
33
+ tag,
34
+ content
35
+ } = await AesGcmCrypto.encrypt(text, false, key);
36
+ return base64Encrypt(`${iv}:${content}:${tag}`);
37
+ } catch (err) {
38
+ throw new Error(`AES encryption failed: ${err?.message || err}`);
39
+ }
22
40
  }
23
41
  export async function aesDecrypt(ciphertext, key) {
42
+ ensureAesAvailable();
24
43
  if (!isBase64(key) || base64ByteLength(key) !== 32) {
25
44
  throw new Error('Encryption key must be base64-encoded 32-byte (256-bit) value');
26
45
  }
27
- const parts = ciphertext.split(':');
28
- const iv = parts[0] ?? '';
29
- const content = parts[1] ?? '';
30
- const tag = parts[2] ?? '';
31
- const decrypted = await AesGcmCrypto.decrypt(content, key, iv, tag, false);
32
- return decrypted;
46
+ try {
47
+ const [iv = '', content = '', tag = ''] = ciphertext.split(':');
48
+ const decrypted = await AesGcmCrypto.decrypt(content, key, iv, tag, false);
49
+ return decrypted;
50
+ } catch (err) {
51
+ throw new Error(`AES decryption failed: ${err?.message || err}`);
52
+ }
33
53
  }
34
54
  export function base64Encrypt(plain) {
35
55
  const utf8 = encodeURIComponent(plain).replace(/%([0-9A-F]{2})/g, (_, p1) => String.fromCharCode(parseInt(p1, 16)));
@@ -1 +1 @@
1
- {"version":3,"names":["AesGcmCrypto","isBase64","input","test","base64ByteLength","b64","cleaned","replace","Math","floor","length","aesEncrypt","text","key","Error","iv","tag","content","encrypt","base64Encrypt","aesDecrypt","ciphertext","parts","split","decrypted","decrypt","plain","utf8","encodeURIComponent","_","p1","String","fromCharCode","parseInt","btoa","base64Decrypt","encoded","binary","atob","map","c","charCodeAt","toString","slice","join","decodeURIComponent"],"sourceRoot":"../../../src","sources":["utils/encryption.ts"],"mappings":";;AAAA;AACA,OAAOA,YAAY,MAAM,6BAA6B;AAEtD,SAASC,QAAQA,CAACC,KAAa,EAAW;EACxC,OAAO,wBAAwB,CAACC,IAAI,CAACD,KAAK,CAAC;AAC7C;AAEA,SAASE,gBAAgBA,CAACC,GAAW,EAAU;EAC7C,MAAMC,OAAO,GAAGD,GAAG,CAACE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;EACtC,OAAOC,IAAI,CAACC,KAAK,CAAEH,OAAO,CAACI,MAAM,GAAG,CAAC,GAAI,CAAC,CAAC;AAC7C;AAEA,OAAO,eAAeC,UAAUA,CAACC,IAAY,EAAEC,GAAW,EAAmB;EAC3E,IAAI,CAACZ,QAAQ,CAACY,GAAG,CAAC,IAAIT,gBAAgB,CAACS,GAAG,CAAC,KAAK,EAAE,EAAE;IAClD,MAAM,IAAIC,KAAK,CACb,+DACF,CAAC;EACH;EACA,MAAM;IAAEC,EAAE;IAAEC,GAAG;IAAEC;EAAQ,CAAC,GAAG,MAAMjB,YAAY,CAACkB,OAAO,CAACN,IAAI,EAAE,KAAK,EAAEC,GAAG,CAAC;EACzE,OAAOM,aAAa,CAAC,GAAGJ,EAAE,IAAIE,OAAO,IAAID,GAAG,EAAE,CAAC;AACjD;AAEA,OAAO,eAAeI,UAAUA,CAC9BC,UAAkB,EAClBR,GAAW,EACM;EACjB,IAAI,CAACZ,QAAQ,CAACY,GAAG,CAAC,IAAIT,gBAAgB,CAACS,GAAG,CAAC,KAAK,EAAE,EAAE;IAClD,MAAM,IAAIC,KAAK,CACb,+DACF,CAAC;EACH;EACA,MAAMQ,KAAK,GAAGD,UAAU,CAACE,KAAK,CAAC,GAAG,CAAC;EACnC,MAAMR,EAAE,GAAGO,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;EACzB,MAAML,OAAO,GAAGK,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;EAC9B,MAAMN,GAAG,GAAGM,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;EAC1B,MAAME,SAAS,GAAG,MAAMxB,YAAY,CAACyB,OAAO,CAACR,OAAO,EAAEJ,GAAG,EAAEE,EAAE,EAAEC,GAAG,EAAE,KAAK,CAAC;EAC1E,OAAOQ,SAAS;AAClB;AAKA,OAAO,SAASL,aAAaA,CAACO,KAAa,EAAU;EACnD,MAAMC,IAAI,GAAGC,kBAAkB,CAACF,KAAK,CAAC,CAACnB,OAAO,CAC5C,iBAAiB,EACjB,CAACsB,CAAC,EAAEC,EAAU,KAAKC,MAAM,CAACC,YAAY,CAACC,QAAQ,CAACH,EAAE,EAAE,EAAE,CAAC,CACzD,CAAC;EACD,OAAOI,IAAI,CAACP,IAAI,CAAC;AACnB;AAEA,OAAO,SAASQ,aAAaA,CAACC,OAAe,EAAU;EACrD,MAAMC,MAAM,GAAGC,IAAI,CAACF,OAAO,CAAC;EAC5B,MAAMT,IAAI,GAAGU,MAAM,CAChBd,KAAK,CAAC,EAAE,CAAC,CACTgB,GAAG,CAAEC,CAAC,IAAK,GAAG,GAAG,CAAC,IAAI,GAAGA,CAAC,CAACC,UAAU,CAAC,CAAC,CAAC,CAACC,QAAQ,CAAC,EAAE,CAAC,EAAEC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CACjEC,IAAI,CAAC,EAAE,CAAC;EACX,OAAOC,kBAAkB,CAAClB,IAAI,CAAC;AACjC","ignoreList":[]}
1
+ {"version":3,"names":["NativeModules","AesGcmCrypto","ensureAesAvailable","nativeModule","RNAesGcmCrypto","Error","encrypt","isBase64","input","test","base64ByteLength","b64","cleaned","replace","Math","floor","length","aesEncrypt","text","key","iv","tag","content","base64Encrypt","err","message","aesDecrypt","ciphertext","split","decrypted","decrypt","plain","utf8","encodeURIComponent","_","p1","String","fromCharCode","parseInt","btoa","base64Decrypt","encoded","binary","atob","map","c","charCodeAt","toString","slice","join","decodeURIComponent"],"sourceRoot":"../../../src","sources":["utils/encryption.ts"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"openMap.d.ts","sourceRoot":"","sources":["../../../../../src/services/navigation/openMap.ts"],"names":[],"mappings":"AASA,wBAAsB,OAAO,CAC3B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAyBf"}
1
+ {"version":3,"file":"openMap.d.ts","sourceRoot":"","sources":["../../../../../src/services/navigation/openMap.ts"],"names":[],"mappings":"AASA,wBAAsB,OAAO,CAC3B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAuCf"}
@@ -1 +1 @@
1
- {"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../../../src/utils/encryption.ts"],"names":[],"mappings":"AAYA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ3E;AAED,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CAYjB;AAKD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMnD;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOrD"}
1
+ {"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../../../src/utils/encryption.ts"],"names":[],"mappings":"AAoCA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgB3E;AAED,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAKD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMnD;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOrD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savers_app/react-native-sdk",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Cross-platform React Native SDK exposing native features (maps, dial pad, browser), device ID/location and session utilities, a URL generator, and a WebView message bridge to trigger actions from web content.",
5
5
  "main": "./lib/module/index.js",
6
6
  "react-native": "./src/index.tsx",
@@ -79,7 +79,7 @@
79
79
  "eslint-plugin-prettier": "^5.5.4",
80
80
  "jest": "^29.7.0",
81
81
  "lefthook": "^2.0.3",
82
- "prettier": "^2.8.8",
82
+ "prettier": "^3.8.1",
83
83
  "react": "19.1.0",
84
84
  "react-native": "0.81.5",
85
85
  "react-native-builder-bob": "^0.40.13",
@@ -2,7 +2,7 @@
2
2
  import { Linking } from 'react-native';
3
3
 
4
4
  // Utilities / Helpers
5
- import { isMapAppAvailable, isValidCoordinates } from '../../utils/validator';
5
+ import { isValidCoordinates } from '../../utils/validator';
6
6
 
7
7
  // Platform / Environment helpers
8
8
  import { isIOS } from '../../utils/platformManager';
@@ -17,23 +17,37 @@ export async function openMap(
17
17
  }
18
18
 
19
19
  const iosUrl = `maps:0,0?q=${encodeURIComponent(label ?? '')}@${lat},${lng}`;
20
- const androidUrl = `geo:0,0?q=${lat},${lng}${
21
- label ? `(${encodeURIComponent(label)})` : ''
22
- }`;
23
- const deepLink = isIOS() ? iosUrl : androidUrl;
24
20
 
25
- const available = await isMapAppAvailable();
26
- if (available) {
27
- await Linking.openURL(deepLink);
21
+ if (isIOS()) {
22
+ try {
23
+ await Linking.openURL(iosUrl);
24
+ return;
25
+ } catch {}
26
+ const browserUrl = `https://maps.apple.com/?q=${encodeURIComponent(
27
+ label ?? ''
28
+ )}&ll=${lat},${lng}`;
29
+ await Linking.openURL(browserUrl);
28
30
  return;
29
31
  }
30
32
 
31
- const browserUrl = isIOS()
32
- ? `https://maps.apple.com/?q=${encodeURIComponent(
33
- label ?? ''
34
- )}&ll=${lat},${lng}`
35
- : `https://www.google.com/maps/search/?api=1&query=${lat},${lng}${
36
- label ? `&query_place_id=${encodeURIComponent(label)}` : ''
37
- }`;
33
+ const encLabel = label ? encodeURIComponent(label) : undefined;
34
+ const query = `${lat},${lng}${encLabel ? `(${encLabel})` : ''}`;
35
+ const candidates = [
36
+ // Prefer geo to show a pin at the destination (not navigation)
37
+ `geo:${lat},${lng}?q=${query}`,
38
+ `geo:0,0?q=${query}`,
39
+ // Fallback to Google Maps custom scheme as a generic search/pin
40
+ `comgooglemaps://?q=${query}`,
41
+ ];
42
+ for (const url of candidates) {
43
+ try {
44
+ await Linking.openURL(url);
45
+ return;
46
+ } catch {}
47
+ }
48
+ const browserQuery = label ? `${label} ${lat},${lng}` : `${lat},${lng}`;
49
+ const browserUrl = `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(
50
+ browserQuery
51
+ )}`;
38
52
  await Linking.openURL(browserUrl);
39
53
  }
@@ -1,6 +1,30 @@
1
- // Third-party libraries
1
+ import { NativeModules } from 'react-native';
2
2
  import AesGcmCrypto from 'react-native-aes-gcm-crypto';
3
3
 
4
+ /**
5
+ * Ensure native module is installed & linked
6
+ */
7
+ function ensureAesAvailable() {
8
+ const nativeModule =
9
+ NativeModules.AesGcmCrypto || NativeModules.RNAesGcmCrypto;
10
+
11
+ if (!AesGcmCrypto || !nativeModule) {
12
+ throw new Error(
13
+ 'react-native-aes-gcm-crypto is not installed or linked correctly.\n\n' +
14
+ 'Fix:\n' +
15
+ '1. yarn add react-native-aes-gcm-crypto\n' +
16
+ '2. cd ios && pod install\n' +
17
+ '3. Rebuild the app\n'
18
+ );
19
+ }
20
+
21
+ if (typeof AesGcmCrypto.encrypt !== 'function') {
22
+ throw new Error(
23
+ 'AES-GCM native functions unavailable. Please rebuild the app.'
24
+ );
25
+ }
26
+ }
27
+
4
28
  function isBase64(input: string): boolean {
5
29
  return /^[A-Za-z0-9+/]+={0,2}$/.test(input);
6
30
  }
@@ -11,30 +35,44 @@ function base64ByteLength(b64: string): number {
11
35
  }
12
36
 
13
37
  export async function aesEncrypt(text: string, key: string): Promise<string> {
38
+ ensureAesAvailable();
39
+
14
40
  if (!isBase64(key) || base64ByteLength(key) !== 32) {
15
41
  throw new Error(
16
42
  'Encryption key must be base64-encoded 32-byte (256-bit) value'
17
43
  );
18
44
  }
19
- const { iv, tag, content } = await AesGcmCrypto.encrypt(text, false, key);
20
- return base64Encrypt(`${iv}:${content}:${tag}`);
45
+
46
+ try {
47
+ const { iv, tag, content } = await AesGcmCrypto.encrypt(text, false, key);
48
+
49
+ return base64Encrypt(`${iv}:${content}:${tag}`);
50
+ } catch (err: any) {
51
+ throw new Error(`AES encryption failed: ${err?.message || err}`);
52
+ }
21
53
  }
22
54
 
23
55
  export async function aesDecrypt(
24
56
  ciphertext: string,
25
57
  key: string
26
58
  ): Promise<string> {
59
+ ensureAesAvailable();
60
+
27
61
  if (!isBase64(key) || base64ByteLength(key) !== 32) {
28
62
  throw new Error(
29
63
  'Encryption key must be base64-encoded 32-byte (256-bit) value'
30
64
  );
31
65
  }
32
- const parts = ciphertext.split(':');
33
- const iv = parts[0] ?? '';
34
- const content = parts[1] ?? '';
35
- const tag = parts[2] ?? '';
36
- const decrypted = await AesGcmCrypto.decrypt(content, key, iv, tag, false);
37
- return decrypted;
66
+
67
+ try {
68
+ const [iv = '', content = '', tag = ''] = ciphertext.split(':');
69
+
70
+ const decrypted = await AesGcmCrypto.decrypt(content, key, iv, tag, false);
71
+
72
+ return decrypted;
73
+ } catch (err: any) {
74
+ throw new Error(`AES decryption failed: ${err?.message || err}`);
75
+ }
38
76
  }
39
77
 
40
78
  declare function btoa(data: string): string;