@oxyhq/core 1.0.2 → 1.1.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.
Files changed (114) hide show
  1. package/dist/cjs/AuthManager.js +19 -9
  2. package/dist/cjs/CrossDomainAuth.js +2 -2
  3. package/dist/cjs/HttpService.js +9 -8
  4. package/dist/cjs/OxyServices.base.js +16 -3
  5. package/dist/cjs/crypto/keyManager.js +29 -24
  6. package/dist/cjs/crypto/polyfill.js +6 -1
  7. package/dist/cjs/crypto/signatureService.js +40 -31
  8. package/dist/cjs/i18n/index.js +36 -45
  9. package/dist/cjs/i18n/locales/ar-SA.json +114 -115
  10. package/dist/cjs/i18n/locales/ca-ES.json +114 -115
  11. package/dist/cjs/i18n/locales/de-DE.json +114 -115
  12. package/dist/cjs/i18n/locales/en-US.json +936 -936
  13. package/dist/cjs/i18n/locales/es-ES.json +924 -924
  14. package/dist/cjs/i18n/locales/fr-FR.json +114 -115
  15. package/dist/cjs/i18n/locales/it-IT.json +114 -115
  16. package/dist/cjs/i18n/locales/ja-JP.json +1 -1
  17. package/dist/cjs/i18n/locales/ko-KR.json +114 -115
  18. package/dist/cjs/i18n/locales/locales/ar-SA.json +120 -0
  19. package/dist/cjs/i18n/locales/locales/ca-ES.json +120 -0
  20. package/dist/cjs/i18n/locales/locales/de-DE.json +120 -0
  21. package/dist/cjs/i18n/locales/locales/en-US.json +956 -0
  22. package/dist/cjs/i18n/locales/locales/es-ES.json +944 -0
  23. package/dist/cjs/i18n/locales/locales/fr-FR.json +120 -0
  24. package/dist/cjs/i18n/locales/locales/it-IT.json +120 -0
  25. package/dist/cjs/i18n/locales/locales/ja-JP.json +119 -0
  26. package/dist/cjs/i18n/locales/locales/ko-KR.json +120 -0
  27. package/dist/cjs/i18n/locales/locales/pt-PT.json +120 -0
  28. package/dist/cjs/i18n/locales/locales/zh-CN.json +120 -0
  29. package/dist/cjs/i18n/locales/pt-PT.json +114 -115
  30. package/dist/cjs/i18n/locales/zh-CN.json +114 -115
  31. package/dist/cjs/mixins/OxyServices.fedcm.js +13 -41
  32. package/dist/cjs/mixins/OxyServices.language.js +5 -2
  33. package/dist/cjs/mixins/OxyServices.privacy.js +2 -1
  34. package/dist/cjs/mixins/OxyServices.security.js +3 -2
  35. package/dist/cjs/shared/utils/debugUtils.js +8 -1
  36. package/dist/cjs/utils/deviceManager.js +3 -1
  37. package/dist/cjs/utils/platform.js +3 -2
  38. package/dist/esm/AuthManager.js +19 -9
  39. package/dist/esm/CrossDomainAuth.js +2 -2
  40. package/dist/esm/HttpService.js +9 -8
  41. package/dist/esm/OxyServices.base.js +16 -3
  42. package/dist/esm/crypto/keyManager.js +29 -24
  43. package/dist/esm/crypto/polyfill.js +6 -1
  44. package/dist/esm/crypto/signatureService.js +40 -31
  45. package/dist/esm/i18n/index.js +11 -23
  46. package/dist/esm/i18n/locales/ar-SA.json +114 -115
  47. package/dist/esm/i18n/locales/ca-ES.json +114 -115
  48. package/dist/esm/i18n/locales/de-DE.json +114 -115
  49. package/dist/esm/i18n/locales/en-US.json +936 -936
  50. package/dist/esm/i18n/locales/es-ES.json +924 -924
  51. package/dist/esm/i18n/locales/fr-FR.json +114 -115
  52. package/dist/esm/i18n/locales/it-IT.json +114 -115
  53. package/dist/esm/i18n/locales/ja-JP.json +1 -1
  54. package/dist/esm/i18n/locales/ko-KR.json +114 -115
  55. package/dist/esm/i18n/locales/locales/ar-SA.json +120 -0
  56. package/dist/esm/i18n/locales/locales/ca-ES.json +120 -0
  57. package/dist/esm/i18n/locales/locales/de-DE.json +120 -0
  58. package/dist/esm/i18n/locales/locales/en-US.json +956 -0
  59. package/dist/esm/i18n/locales/locales/es-ES.json +944 -0
  60. package/dist/esm/i18n/locales/locales/fr-FR.json +120 -0
  61. package/dist/esm/i18n/locales/locales/it-IT.json +120 -0
  62. package/dist/esm/i18n/locales/locales/ja-JP.json +119 -0
  63. package/dist/esm/i18n/locales/locales/ko-KR.json +120 -0
  64. package/dist/esm/i18n/locales/locales/pt-PT.json +120 -0
  65. package/dist/esm/i18n/locales/locales/zh-CN.json +120 -0
  66. package/dist/esm/i18n/locales/pt-PT.json +114 -115
  67. package/dist/esm/i18n/locales/zh-CN.json +114 -115
  68. package/dist/esm/mixins/OxyServices.fedcm.js +13 -41
  69. package/dist/esm/mixins/OxyServices.language.js +5 -2
  70. package/dist/esm/mixins/OxyServices.privacy.js +2 -1
  71. package/dist/esm/mixins/OxyServices.security.js +3 -2
  72. package/dist/esm/shared/utils/debugUtils.js +8 -1
  73. package/dist/esm/utils/deviceManager.js +3 -1
  74. package/dist/esm/utils/platform.js +3 -2
  75. package/dist/types/CrossDomainAuth.d.ts +2 -2
  76. package/dist/types/OxyServices.base.d.ts +4 -1
  77. package/dist/types/OxyServices.d.ts +13 -0
  78. package/dist/types/index.d.ts +3 -0
  79. package/dist/types/mixins/OxyServices.analytics.d.ts +2 -0
  80. package/dist/types/mixins/OxyServices.assets.d.ts +2 -0
  81. package/dist/types/mixins/OxyServices.auth.d.ts +2 -0
  82. package/dist/types/mixins/OxyServices.developer.d.ts +2 -0
  83. package/dist/types/mixins/OxyServices.devices.d.ts +2 -0
  84. package/dist/types/mixins/OxyServices.features.d.ts +2 -0
  85. package/dist/types/mixins/OxyServices.fedcm.d.ts +4 -2
  86. package/dist/types/mixins/OxyServices.karma.d.ts +2 -0
  87. package/dist/types/mixins/OxyServices.language.d.ts +2 -0
  88. package/dist/types/mixins/OxyServices.location.d.ts +2 -0
  89. package/dist/types/mixins/OxyServices.payment.d.ts +2 -0
  90. package/dist/types/mixins/OxyServices.popup.d.ts +2 -0
  91. package/dist/types/mixins/OxyServices.privacy.d.ts +2 -0
  92. package/dist/types/mixins/OxyServices.redirect.d.ts +2 -0
  93. package/dist/types/mixins/OxyServices.security.d.ts +2 -0
  94. package/dist/types/mixins/OxyServices.user.d.ts +2 -0
  95. package/dist/types/mixins/OxyServices.utility.d.ts +2 -0
  96. package/package.json +1 -2
  97. package/src/AuthManager.ts +25 -15
  98. package/src/CrossDomainAuth.ts +2 -2
  99. package/src/HttpService.ts +9 -8
  100. package/src/OxyServices.base.ts +21 -4
  101. package/src/OxyServices.ts +23 -2
  102. package/src/crypto/keyManager.ts +30 -25
  103. package/src/crypto/polyfill.ts +6 -1
  104. package/src/crypto/signatureService.ts +43 -37
  105. package/src/i18n/index.ts +33 -45
  106. package/src/index.ts +3 -0
  107. package/src/mixins/OxyServices.fedcm.ts +14 -44
  108. package/src/mixins/OxyServices.language.ts +6 -3
  109. package/src/mixins/OxyServices.privacy.ts +2 -1
  110. package/src/mixins/OxyServices.security.ts +3 -2
  111. package/src/shared/utils/__tests__/debugUtils.test.ts +55 -0
  112. package/src/shared/utils/debugUtils.ts +6 -1
  113. package/src/utils/deviceManager.ts +4 -2
  114. package/src/utils/platform.ts +3 -2
@@ -10,6 +10,7 @@
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
11
  exports.AuthManager = void 0;
12
12
  exports.createAuthManager = createAuthManager;
13
+ const asyncUtils_1 = require("./utils/asyncUtils");
13
14
  /**
14
15
  * Storage keys used by AuthManager.
15
16
  */
@@ -210,19 +211,28 @@ class AuthManager {
210
211
  return false;
211
212
  }
212
213
  try {
213
- // Cast httpService to proper type (needed due to mixin composition)
214
- const httpService = this.oxyServices.httpService;
215
- const response = await httpService.request({
216
- method: 'POST',
217
- url: '/api/auth/refresh',
218
- data: { refreshToken },
219
- cache: false,
214
+ await (0, asyncUtils_1.retryAsync)(async () => {
215
+ const httpService = this.oxyServices.httpService;
216
+ const response = await httpService.request({
217
+ method: 'POST',
218
+ url: '/api/auth/refresh',
219
+ data: { refreshToken },
220
+ cache: false,
221
+ });
222
+ await this.handleAuthSuccess(response, 'credentials');
223
+ }, 2, // 2 retries = 3 total attempts
224
+ 1000, // 1s base delay with exponential backoff + jitter
225
+ (error) => {
226
+ // Don't retry on 4xx client errors (invalid/revoked token)
227
+ const status = error?.status ?? error?.response?.status;
228
+ if (status && status >= 400 && status < 500)
229
+ return false;
230
+ return true;
220
231
  });
221
- await this.handleAuthSuccess(response, 'credentials');
222
232
  return true;
223
233
  }
224
234
  catch {
225
- // Refresh failed, clear session and update state
235
+ // All retry attempts exhausted, clear session
226
236
  await this.clearSession();
227
237
  this.currentUser = null;
228
238
  this.notifyListeners();
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * Usage:
13
13
  * ```typescript
14
- * import { CrossDomainAuth } from '@oxyhq/services';
14
+ * import { CrossDomainAuth } from '@oxyhq/core';
15
15
  *
16
16
  * const auth = new CrossDomainAuth(oxyServices);
17
17
  *
@@ -238,7 +238,7 @@ exports.CrossDomainAuth = CrossDomainAuth;
238
238
  *
239
239
  * @example
240
240
  * ```typescript
241
- * import { createCrossDomainAuth } from '@oxyhq/services';
241
+ * import { createCrossDomainAuth } from '@oxyhq/core';
242
242
  *
243
243
  * const oxyServices = new OxyServices({ baseURL: 'https://api.oxy.so' });
244
244
  * const auth = createCrossDomainAuth(oxyServices);
@@ -19,6 +19,7 @@ const cache_1 = require("./utils/cache");
19
19
  const requestUtils_1 = require("./utils/requestUtils");
20
20
  const asyncUtils_1 = require("./utils/asyncUtils");
21
21
  const errorUtils_1 = require("./utils/errorUtils");
22
+ const debugUtils_1 = require("./shared/utils/debugUtils");
22
23
  const jwt_decode_1 = require("jwt-decode");
23
24
  const platform_1 = require("./utils/platform");
24
25
  /**
@@ -189,7 +190,7 @@ class HttpService {
189
190
  headers['X-Native-App'] = 'true';
190
191
  }
191
192
  // Debug logging for CSRF issues
192
- if (isStateChangingMethod && __DEV__) {
193
+ if (isStateChangingMethod && (0, debugUtils_1.isDev)()) {
193
194
  console.log('[HttpService] CSRF Debug:', {
194
195
  url,
195
196
  method,
@@ -373,20 +374,20 @@ class HttpService {
373
374
  // Return cached token if available
374
375
  const cachedToken = this.tokenStore.getCsrfToken();
375
376
  if (cachedToken) {
376
- if (__DEV__)
377
+ if ((0, debugUtils_1.isDev)())
377
378
  console.log('[HttpService] Using cached CSRF token');
378
379
  return cachedToken;
379
380
  }
380
381
  // Deduplicate concurrent CSRF token fetches
381
382
  const existingPromise = this.tokenStore.getCsrfTokenFetchPromise();
382
383
  if (existingPromise) {
383
- if (__DEV__)
384
+ if ((0, debugUtils_1.isDev)())
384
385
  console.log('[HttpService] Waiting for existing CSRF fetch');
385
386
  return existingPromise;
386
387
  }
387
388
  const fetchPromise = (async () => {
388
389
  try {
389
- if (__DEV__)
390
+ if ((0, debugUtils_1.isDev)())
390
391
  console.log('[HttpService] Fetching CSRF token from:', `${this.baseURL}/api/csrf-token`);
391
392
  // Use AbortController for timeout (more compatible than AbortSignal.timeout)
392
393
  const controller = new AbortController();
@@ -398,11 +399,11 @@ class HttpService {
398
399
  signal: controller.signal,
399
400
  });
400
401
  clearTimeout(timeoutId);
401
- if (__DEV__)
402
+ if ((0, debugUtils_1.isDev)())
402
403
  console.log('[HttpService] CSRF fetch response:', response.status, response.ok);
403
404
  if (response.ok) {
404
405
  const data = await response.json();
405
- if (__DEV__)
406
+ if ((0, debugUtils_1.isDev)())
406
407
  console.log('[HttpService] CSRF response data:', data);
407
408
  const token = data.csrfToken || null;
408
409
  this.tokenStore.setCsrfToken(token);
@@ -416,13 +417,13 @@ class HttpService {
416
417
  this.logger.debug('CSRF token from header');
417
418
  return headerToken;
418
419
  }
419
- if (__DEV__)
420
+ if ((0, debugUtils_1.isDev)())
420
421
  console.log('[HttpService] CSRF fetch failed with status:', response.status);
421
422
  this.logger.warn('Failed to fetch CSRF token:', response.status);
422
423
  return null;
423
424
  }
424
425
  catch (error) {
425
- if (__DEV__)
426
+ if ((0, debugUtils_1.isDev)())
426
427
  console.log('[HttpService] CSRF fetch error:', error);
427
428
  this.logger.warn('CSRF token fetch error:', error);
428
429
  return null;
@@ -15,6 +15,8 @@ const OxyServices_errors_1 = require("./OxyServices.errors");
15
15
  */
16
16
  class OxyServicesBase {
17
17
  constructor(...args) {
18
+ /** @internal */ this._cachedUserId = undefined;
19
+ /** @internal */ this._cachedAccessToken = null;
18
20
  const config = args[0];
19
21
  if (!config || typeof config !== 'object') {
20
22
  throw new Error('OxyConfig is required');
@@ -98,20 +100,31 @@ class OxyServicesBase {
98
100
  */
99
101
  clearTokens() {
100
102
  this.httpService.clearTokens();
103
+ this._cachedUserId = undefined;
104
+ this._cachedAccessToken = null;
101
105
  }
102
106
  /**
103
- * Get the current user ID from the access token
107
+ * Get the current user ID from the access token.
108
+ * Caches the decoded value and invalidates when the token changes.
104
109
  */
105
110
  getCurrentUserId() {
106
111
  const accessToken = this.httpService.getAccessToken();
112
+ // Return cached value if token hasn't changed
113
+ if (accessToken === this._cachedAccessToken && this._cachedUserId !== undefined) {
114
+ return this._cachedUserId;
115
+ }
116
+ this._cachedAccessToken = accessToken;
107
117
  if (!accessToken) {
118
+ this._cachedUserId = null;
108
119
  return null;
109
120
  }
110
121
  try {
111
122
  const decoded = (0, jwt_decode_1.jwtDecode)(accessToken);
112
- return decoded.userId || decoded.id || null;
123
+ this._cachedUserId = decoded.userId || decoded.id || null;
124
+ return this._cachedUserId;
113
125
  }
114
- catch (error) {
126
+ catch {
127
+ this._cachedUserId = null;
115
128
  return null;
116
129
  }
117
130
  }
@@ -43,6 +43,7 @@ exports.KeyManager = void 0;
43
43
  const elliptic_1 = require("elliptic");
44
44
  const platform_1 = require("../utils/platform");
45
45
  const loggerUtils_1 = require("../utils/loggerUtils");
46
+ const debugUtils_1 = require("../shared/utils/debugUtils");
46
47
  // Lazy imports for React Native specific modules
47
48
  let SecureStore = null;
48
49
  let ExpoCrypto = null;
@@ -77,7 +78,9 @@ const ANDROID_ACCOUNT_TYPE = 'com.oxy.account';
77
78
  async function initSecureStore() {
78
79
  if (!SecureStore) {
79
80
  try {
80
- SecureStore = await Promise.resolve().then(() => __importStar(require('expo-secure-store')));
81
+ // Variable indirection prevents bundlers (Vite, webpack) from statically resolving this
82
+ const moduleName = 'expo-secure-store';
83
+ SecureStore = await Promise.resolve(`${moduleName}`).then(s => __importStar(require(s)));
81
84
  }
82
85
  catch (error) {
83
86
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -110,7 +113,9 @@ function isWebPlatform() {
110
113
  }
111
114
  async function initExpoCrypto() {
112
115
  if (!ExpoCrypto) {
113
- ExpoCrypto = await Promise.resolve().then(() => __importStar(require('expo-crypto')));
116
+ // Variable indirection prevents bundlers (Vite, webpack) from statically resolving this
117
+ const moduleName = 'expo-crypto';
118
+ ExpoCrypto = await Promise.resolve(`${moduleName}`).then(s => __importStar(require(s)));
114
119
  }
115
120
  return ExpoCrypto;
116
121
  }
@@ -237,7 +242,7 @@ class KeyManager {
237
242
  // Update cache
238
243
  KeyManager.cachedSharedPublicKey = publicKey;
239
244
  KeyManager.cachedHasSharedIdentity = true;
240
- if (__DEV__) {
245
+ if ((0, debugUtils_1.isDev)()) {
241
246
  loggerUtils_1.logger.debug('Shared identity created successfully', { component: 'KeyManager' });
242
247
  }
243
248
  return publicKey;
@@ -271,7 +276,7 @@ class KeyManager {
271
276
  return publicKey;
272
277
  }
273
278
  catch (error) {
274
- if (__DEV__) {
279
+ if ((0, debugUtils_1.isDev)()) {
275
280
  loggerUtils_1.logger.warn('Failed to get shared public key', { component: 'KeyManager' }, error);
276
281
  }
277
282
  KeyManager.cachedSharedPublicKey = null;
@@ -304,7 +309,7 @@ class KeyManager {
304
309
  return privateKey;
305
310
  }
306
311
  catch (error) {
307
- if (__DEV__) {
312
+ if ((0, debugUtils_1.isDev)()) {
308
313
  loggerUtils_1.logger.warn('Failed to get shared private key', { component: 'KeyManager' }, error);
309
314
  }
310
315
  return null;
@@ -331,7 +336,7 @@ class KeyManager {
331
336
  return hasShared;
332
337
  }
333
338
  catch (error) {
334
- if (__DEV__) {
339
+ if ((0, debugUtils_1.isDev)()) {
335
340
  loggerUtils_1.logger.warn('Failed to check shared identity', { component: 'KeyManager' }, error);
336
341
  }
337
342
  KeyManager.cachedHasSharedIdentity = false;
@@ -374,7 +379,7 @@ class KeyManager {
374
379
  // Update cache
375
380
  KeyManager.cachedSharedPublicKey = publicKey;
376
381
  KeyManager.cachedHasSharedIdentity = true;
377
- if (__DEV__) {
382
+ if ((0, debugUtils_1.isDev)()) {
378
383
  loggerUtils_1.logger.debug('Shared identity imported successfully', { component: 'KeyManager' });
379
384
  }
380
385
  return publicKey;
@@ -408,12 +413,12 @@ class KeyManager {
408
413
  await store.setItemAsync(STORAGE_KEYS.SHARED_SESSION_ID, sessionId);
409
414
  await store.setItemAsync(STORAGE_KEYS.SHARED_SESSION_TOKEN, accessToken);
410
415
  }
411
- if (__DEV__) {
416
+ if ((0, debugUtils_1.isDev)()) {
412
417
  loggerUtils_1.logger.debug('Shared session stored successfully', { component: 'KeyManager' });
413
418
  }
414
419
  }
415
420
  catch (error) {
416
- if (__DEV__) {
421
+ if ((0, debugUtils_1.isDev)()) {
417
422
  loggerUtils_1.logger.error('Failed to store shared session', error, { component: 'KeyManager' });
418
423
  }
419
424
  throw error;
@@ -453,7 +458,7 @@ class KeyManager {
453
458
  return { sessionId, accessToken };
454
459
  }
455
460
  catch (error) {
456
- if (__DEV__) {
461
+ if ((0, debugUtils_1.isDev)()) {
457
462
  loggerUtils_1.logger.warn('Failed to get shared session', { component: 'KeyManager' }, error);
458
463
  }
459
464
  return null;
@@ -483,12 +488,12 @@ class KeyManager {
483
488
  await store.deleteItemAsync(STORAGE_KEYS.SHARED_SESSION_ID);
484
489
  await store.deleteItemAsync(STORAGE_KEYS.SHARED_SESSION_TOKEN);
485
490
  }
486
- if (__DEV__) {
491
+ if ((0, debugUtils_1.isDev)()) {
487
492
  loggerUtils_1.logger.debug('Shared session cleared successfully', { component: 'KeyManager' });
488
493
  }
489
494
  }
490
495
  catch (error) {
491
- if (__DEV__) {
496
+ if ((0, debugUtils_1.isDev)()) {
492
497
  loggerUtils_1.logger.error('Failed to clear shared session', error, { component: 'KeyManager' });
493
498
  }
494
499
  }
@@ -510,7 +515,7 @@ class KeyManager {
510
515
  // Check if we already have a shared identity
511
516
  const hasShared = await KeyManager.hasSharedIdentity();
512
517
  if (hasShared) {
513
- if (__DEV__) {
518
+ if ((0, debugUtils_1.isDev)()) {
514
519
  loggerUtils_1.logger.debug('Shared identity already exists, skipping migration', { component: 'KeyManager' });
515
520
  }
516
521
  return true;
@@ -518,20 +523,20 @@ class KeyManager {
518
523
  // Get local identity
519
524
  const privateKey = await KeyManager.getPrivateKey();
520
525
  if (!privateKey) {
521
- if (__DEV__) {
526
+ if ((0, debugUtils_1.isDev)()) {
522
527
  loggerUtils_1.logger.debug('No local identity to migrate', { component: 'KeyManager' });
523
528
  }
524
529
  return false;
525
530
  }
526
531
  // Import to shared storage
527
532
  await KeyManager.importSharedIdentity(privateKey);
528
- if (__DEV__) {
533
+ if ((0, debugUtils_1.isDev)()) {
529
534
  loggerUtils_1.logger.debug('Successfully migrated local identity to shared identity', { component: 'KeyManager' });
530
535
  }
531
536
  return true;
532
537
  }
533
538
  catch (error) {
534
- if (__DEV__) {
539
+ if ((0, debugUtils_1.isDev)()) {
535
540
  loggerUtils_1.logger.error('Failed to migrate to shared identity', error, { component: 'KeyManager' });
536
541
  }
537
542
  return false;
@@ -591,7 +596,7 @@ class KeyManager {
591
596
  catch (error) {
592
597
  // If secure store is not available, return null (no identity)
593
598
  // This allows the app to continue functioning even if secure store fails to load
594
- if (__DEV__) {
599
+ if ((0, debugUtils_1.isDev)()) {
595
600
  loggerUtils_1.logger.warn('Failed to access secure store', { component: 'KeyManager' }, error);
596
601
  }
597
602
  return null;
@@ -618,7 +623,7 @@ class KeyManager {
618
623
  // If secure store is not available, return null (no identity)
619
624
  // Cache null to avoid repeated failed attempts
620
625
  KeyManager.cachedPublicKey = null;
621
- if (__DEV__) {
626
+ if ((0, debugUtils_1.isDev)()) {
622
627
  loggerUtils_1.logger.warn('Failed to access secure store', { component: 'KeyManager' }, error);
623
628
  }
624
629
  return null;
@@ -645,7 +650,7 @@ class KeyManager {
645
650
  // If we can't check, assume no identity (safer default)
646
651
  // Cache false to avoid repeated failed attempts
647
652
  KeyManager.cachedHasIdentity = false;
648
- if (__DEV__) {
653
+ if ((0, debugUtils_1.isDev)()) {
649
654
  loggerUtils_1.logger.warn('Failed to check identity', { component: 'KeyManager' }, error);
650
655
  }
651
656
  return false;
@@ -678,12 +683,12 @@ class KeyManager {
678
683
  if (!skipBackup) {
679
684
  try {
680
685
  const backupSuccess = await KeyManager.backupIdentity();
681
- if (!backupSuccess && typeof __DEV__ !== 'undefined' && __DEV__) {
686
+ if (!backupSuccess && (0, debugUtils_1.isDev)()) {
682
687
  loggerUtils_1.logger.warn('Failed to backup identity before deletion - proceeding anyway', { component: 'KeyManager' });
683
688
  }
684
689
  }
685
690
  catch (backupError) {
686
- if (typeof __DEV__ !== 'undefined' && __DEV__) {
691
+ if ((0, debugUtils_1.isDev)()) {
687
692
  loggerUtils_1.logger.warn('Failed to backup identity before deletion', { component: 'KeyManager' }, backupError);
688
693
  }
689
694
  }
@@ -728,7 +733,7 @@ class KeyManager {
728
733
  return true;
729
734
  }
730
735
  catch (error) {
731
- if (typeof __DEV__ !== 'undefined' && __DEV__) {
736
+ if ((0, debugUtils_1.isDev)()) {
732
737
  loggerUtils_1.logger.error('Failed to backup identity', error, { component: 'KeyManager' });
733
738
  }
734
739
  return false;
@@ -768,7 +773,7 @@ class KeyManager {
768
773
  return true;
769
774
  }
770
775
  catch (error) {
771
- if (typeof __DEV__ !== 'undefined' && __DEV__) {
776
+ if ((0, debugUtils_1.isDev)()) {
772
777
  loggerUtils_1.logger.error('Identity integrity check failed', error, { component: 'KeyManager' });
773
778
  }
774
779
  return false;
@@ -816,7 +821,7 @@ class KeyManager {
816
821
  return false;
817
822
  }
818
823
  catch (error) {
819
- if (typeof __DEV__ !== 'undefined' && __DEV__) {
824
+ if ((0, debugUtils_1.isDev)()) {
820
825
  loggerUtils_1.logger.error('Failed to restore identity from backup', error, { component: 'KeyManager' });
821
826
  }
822
827
  return false;
@@ -35,7 +35,12 @@ function getRandomBytesSync(byteCount) {
35
35
  if (!expoCryptoLoadAttempted) {
36
36
  expoCryptoLoadAttempted = true;
37
37
  try {
38
- expoCryptoModule = require('expo-crypto');
38
+ // Only use require() in CJS environments (Metro/Node). In ESM (Vite/browser),
39
+ // crypto.getRandomValues exists natively so this code path is never reached.
40
+ if (typeof require !== 'undefined') {
41
+ const moduleName = 'expo-crypto';
42
+ expoCryptoModule = require(moduleName);
43
+ }
39
44
  }
40
45
  catch {
41
46
  // expo-crypto not available — expected in non-RN environments
@@ -62,7 +62,9 @@ function isNodeJS() {
62
62
  */
63
63
  async function initExpoCrypto() {
64
64
  if (!ExpoCrypto) {
65
- ExpoCrypto = await Promise.resolve().then(() => __importStar(require('expo-crypto')));
65
+ // Variable indirection prevents bundlers (Vite, webpack) from statically resolving this
66
+ const moduleName = 'expo-crypto';
67
+ ExpoCrypto = await Promise.resolve(`${moduleName}`).then(s => __importStar(require(s)));
66
68
  }
67
69
  return ExpoCrypto;
68
70
  }
@@ -70,25 +72,29 @@ async function initExpoCrypto() {
70
72
  * Compute SHA-256 hash of a string
71
73
  */
72
74
  async function sha256(message) {
73
- // In React Native, always use expo-crypto
74
- if (isReactNative() || !isNodeJS()) {
75
+ // In React Native, use expo-crypto
76
+ if (isReactNative()) {
75
77
  const Crypto = await initExpoCrypto();
76
78
  return Crypto.digestStringAsync(Crypto.CryptoDigestAlgorithm.SHA256, message);
77
79
  }
78
80
  // In Node.js, use Node's crypto module
79
- // Use Function constructor to prevent Metro bundler from statically analyzing this require
80
- // This ensures the require is only evaluated in Node.js runtime, not during Metro bundling
81
- try {
82
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
83
- const getCrypto = new Function('return require("crypto")');
84
- const crypto = getCrypto();
85
- return crypto.createHash('sha256').update(message).digest('hex');
86
- }
87
- catch (error) {
88
- // Fallback to expo-crypto if Node crypto fails
89
- const Crypto = await initExpoCrypto();
90
- return Crypto.digestStringAsync(Crypto.CryptoDigestAlgorithm.SHA256, message);
81
+ if (isNodeJS()) {
82
+ try {
83
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
84
+ const getCrypto = new Function('return require("crypto")');
85
+ const nodeCrypto = getCrypto();
86
+ return nodeCrypto.createHash('sha256').update(message).digest('hex');
87
+ }
88
+ catch {
89
+ // Fall through to Web Crypto API
90
+ }
91
91
  }
92
+ // Browser: use Web Crypto API
93
+ const encoder = new TextEncoder();
94
+ const data = encoder.encode(message);
95
+ const hashBuffer = await globalThis.crypto.subtle.digest('SHA-256', data);
96
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
97
+ return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
92
98
  }
93
99
  class SignatureService {
94
100
  /**
@@ -96,29 +102,32 @@ class SignatureService {
96
102
  * Uses expo-crypto in React Native, crypto.randomBytes in Node.js
97
103
  */
98
104
  static async generateChallenge() {
99
- if (isReactNative() || !isNodeJS()) {
100
- // Use expo-crypto for React Native (expo-random is deprecated)
105
+ // In React Native, use expo-crypto
106
+ if (isReactNative()) {
101
107
  const Crypto = await initExpoCrypto();
102
108
  const randomBytes = await Crypto.getRandomBytesAsync(32);
103
109
  return Array.from(randomBytes)
104
110
  .map((b) => b.toString(16).padStart(2, '0'))
105
111
  .join('');
106
112
  }
107
- // Node.js fallback
108
- try {
109
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
110
- const getCrypto = new Function('return require("crypto")');
111
- const crypto = getCrypto();
112
- return crypto.randomBytes(32).toString('hex');
113
- }
114
- catch (error) {
115
- // Fallback to expo-crypto if Node crypto fails
116
- const Crypto = await initExpoCrypto();
117
- const randomBytes = await Crypto.getRandomBytesAsync(32);
118
- return Array.from(randomBytes)
119
- .map((b) => b.toString(16).padStart(2, '0'))
120
- .join('');
113
+ // In Node.js, use Node's crypto module
114
+ if (isNodeJS()) {
115
+ try {
116
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
117
+ const getCrypto = new Function('return require("crypto")');
118
+ const nodeCrypto = getCrypto();
119
+ return nodeCrypto.randomBytes(32).toString('hex');
120
+ }
121
+ catch {
122
+ // Fall through to Web Crypto API
123
+ }
121
124
  }
125
+ // Browser: use Web Crypto API
126
+ const bytes = new Uint8Array(32);
127
+ globalThis.crypto.getRandomValues(bytes);
128
+ return Array.from(bytes)
129
+ .map(b => b.toString(16).padStart(2, '0'))
130
+ .join('');
122
131
  }
123
132
  /**
124
133
  * Hash a message using SHA-256
@@ -1,53 +1,44 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.translate = translate;
4
7
  exports.hasKey = hasKey;
5
- // Use JSON locale files (RN Metro supports static requires reliably)
6
- // eslint-disable-next-line @typescript-eslint/no-var-requires
7
- const enUS = require('./locales/en-US.json');
8
- // eslint-disable-next-line @typescript-eslint/no-var-requires
9
- const esES = require('./locales/es-ES.json');
10
- // eslint-disable-next-line @typescript-eslint/no-var-requires
11
- const caES = require('./locales/ca-ES.json');
12
- // eslint-disable-next-line @typescript-eslint/no-var-requires
13
- const frFR = require('./locales/fr-FR.json');
14
- // eslint-disable-next-line @typescript-eslint/no-var-requires
15
- const deDE = require('./locales/de-DE.json');
16
- // eslint-disable-next-line @typescript-eslint/no-var-requires
17
- const itIT = require('./locales/it-IT.json');
18
- // eslint-disable-next-line @typescript-eslint/no-var-requires
19
- const ptPT = require('./locales/pt-PT.json');
20
- // eslint-disable-next-line @typescript-eslint/no-var-requires
21
- const jaJP = require('./locales/ja-JP.json');
22
- // eslint-disable-next-line @typescript-eslint/no-var-requires
23
- const koKR = require('./locales/ko-KR.json');
24
- // eslint-disable-next-line @typescript-eslint/no-var-requires
25
- const zhCN = require('./locales/zh-CN.json');
26
- // eslint-disable-next-line @typescript-eslint/no-var-requires
27
- const arSA = require('./locales/ar-SA.json');
8
+ const en_US_json_1 = __importDefault(require("./locales/en-US.json"));
9
+ const es_ES_json_1 = __importDefault(require("./locales/es-ES.json"));
10
+ const ca_ES_json_1 = __importDefault(require("./locales/ca-ES.json"));
11
+ const fr_FR_json_1 = __importDefault(require("./locales/fr-FR.json"));
12
+ const de_DE_json_1 = __importDefault(require("./locales/de-DE.json"));
13
+ const it_IT_json_1 = __importDefault(require("./locales/it-IT.json"));
14
+ const pt_PT_json_1 = __importDefault(require("./locales/pt-PT.json"));
15
+ const ja_JP_json_1 = __importDefault(require("./locales/ja-JP.json"));
16
+ const ko_KR_json_1 = __importDefault(require("./locales/ko-KR.json"));
17
+ const zh_CN_json_1 = __importDefault(require("./locales/zh-CN.json"));
18
+ const ar_SA_json_1 = __importDefault(require("./locales/ar-SA.json"));
28
19
  const DICTS = {
29
- 'en': enUS,
30
- 'en-US': enUS,
31
- 'es': esES,
32
- 'es-ES': esES,
33
- 'ca': caES,
34
- 'ca-ES': caES,
35
- 'fr': frFR,
36
- 'fr-FR': frFR,
37
- 'de': deDE,
38
- 'de-DE': deDE,
39
- 'it': itIT,
40
- 'it-IT': itIT,
41
- 'pt': ptPT,
42
- 'pt-PT': ptPT,
43
- 'ja': jaJP,
44
- 'ja-JP': jaJP,
45
- 'ko': koKR,
46
- 'ko-KR': koKR,
47
- 'zh': zhCN,
48
- 'zh-CN': zhCN,
49
- 'ar': arSA,
50
- 'ar-SA': arSA,
20
+ 'en': en_US_json_1.default,
21
+ 'en-US': en_US_json_1.default,
22
+ 'es': es_ES_json_1.default,
23
+ 'es-ES': es_ES_json_1.default,
24
+ 'ca': ca_ES_json_1.default,
25
+ 'ca-ES': ca_ES_json_1.default,
26
+ 'fr': fr_FR_json_1.default,
27
+ 'fr-FR': fr_FR_json_1.default,
28
+ 'de': de_DE_json_1.default,
29
+ 'de-DE': de_DE_json_1.default,
30
+ 'it': it_IT_json_1.default,
31
+ 'it-IT': it_IT_json_1.default,
32
+ 'pt': pt_PT_json_1.default,
33
+ 'pt-PT': pt_PT_json_1.default,
34
+ 'ja': ja_JP_json_1.default,
35
+ 'ja-JP': ja_JP_json_1.default,
36
+ 'ko': ko_KR_json_1.default,
37
+ 'ko-KR': ko_KR_json_1.default,
38
+ 'zh': zh_CN_json_1.default,
39
+ 'zh-CN': zh_CN_json_1.default,
40
+ 'ar': ar_SA_json_1.default,
41
+ 'ar-SA': ar_SA_json_1.default,
51
42
  };
52
43
  const FALLBACK = 'en-US';
53
44
  function getNested(obj, path) {