@oxyhq/core 1.11.11 → 1.11.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.
Files changed (130) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/CrossDomainAuth.js +3 -1
  3. package/dist/cjs/HttpService.js +227 -51
  4. package/dist/cjs/OxyServices.base.js +9 -0
  5. package/dist/cjs/OxyServices.js +8 -3
  6. package/dist/cjs/crypto/index.js +3 -1
  7. package/dist/cjs/crypto/keyManager.js +476 -172
  8. package/dist/cjs/crypto/polyfill.js +14 -65
  9. package/dist/cjs/crypto/recoveryPhrase.js +30 -11
  10. package/dist/cjs/crypto/signatureService.js +25 -60
  11. package/dist/cjs/i18n/locales/en-US.json +46 -1
  12. package/dist/cjs/i18n/locales/es-ES.json +46 -1
  13. package/dist/cjs/i18n/locales/locales/en-US.json +46 -1
  14. package/dist/cjs/i18n/locales/locales/es-ES.json +46 -1
  15. package/dist/cjs/index.js +7 -2
  16. package/dist/cjs/mixins/OxyServices.assets.js +9 -4
  17. package/dist/cjs/mixins/OxyServices.auth.js +27 -0
  18. package/dist/cjs/mixins/OxyServices.contacts.js +50 -0
  19. package/dist/cjs/mixins/OxyServices.features.js +0 -11
  20. package/dist/cjs/mixins/OxyServices.fedcm.js +4 -3
  21. package/dist/cjs/mixins/OxyServices.language.js +5 -36
  22. package/dist/cjs/mixins/OxyServices.redirect.js +6 -2
  23. package/dist/cjs/mixins/OxyServices.security.js +13 -2
  24. package/dist/cjs/mixins/OxyServices.user.js +70 -38
  25. package/dist/cjs/mixins/OxyServices.utility.js +19 -43
  26. package/dist/cjs/mixins/index.js +11 -3
  27. package/dist/cjs/utils/accountUtils.js +71 -2
  28. package/dist/cjs/utils/asyncUtils.js +34 -5
  29. package/dist/cjs/utils/deviceManager.js +5 -36
  30. package/dist/cjs/utils/platformCrypto.js +165 -0
  31. package/dist/cjs/utils/platformCrypto.native.js +123 -0
  32. package/dist/esm/.tsbuildinfo +1 -1
  33. package/dist/esm/CrossDomainAuth.js +3 -1
  34. package/dist/esm/HttpService.js +228 -52
  35. package/dist/esm/OxyServices.base.js +9 -0
  36. package/dist/esm/OxyServices.js +8 -3
  37. package/dist/esm/crypto/index.js +1 -1
  38. package/dist/esm/crypto/keyManager.js +473 -138
  39. package/dist/esm/crypto/polyfill.js +14 -32
  40. package/dist/esm/crypto/recoveryPhrase.js +30 -11
  41. package/dist/esm/crypto/signatureService.js +25 -27
  42. package/dist/esm/i18n/locales/en-US.json +46 -1
  43. package/dist/esm/i18n/locales/es-ES.json +46 -1
  44. package/dist/esm/i18n/locales/locales/en-US.json +46 -1
  45. package/dist/esm/i18n/locales/locales/es-ES.json +46 -1
  46. package/dist/esm/index.js +2 -2
  47. package/dist/esm/mixins/OxyServices.assets.js +9 -4
  48. package/dist/esm/mixins/OxyServices.auth.js +27 -0
  49. package/dist/esm/mixins/OxyServices.contacts.js +47 -0
  50. package/dist/esm/mixins/OxyServices.features.js +0 -11
  51. package/dist/esm/mixins/OxyServices.fedcm.js +4 -3
  52. package/dist/esm/mixins/OxyServices.language.js +5 -3
  53. package/dist/esm/mixins/OxyServices.redirect.js +6 -2
  54. package/dist/esm/mixins/OxyServices.security.js +13 -2
  55. package/dist/esm/mixins/OxyServices.user.js +70 -38
  56. package/dist/esm/mixins/OxyServices.utility.js +19 -10
  57. package/dist/esm/mixins/index.js +11 -3
  58. package/dist/esm/utils/accountUtils.js +67 -1
  59. package/dist/esm/utils/asyncUtils.js +34 -5
  60. package/dist/esm/utils/deviceManager.js +5 -3
  61. package/dist/esm/utils/platformCrypto.js +125 -0
  62. package/dist/esm/utils/platformCrypto.native.js +80 -0
  63. package/dist/types/.tsbuildinfo +1 -1
  64. package/dist/types/HttpService.d.ts +47 -3
  65. package/dist/types/OxyServices.base.d.ts +7 -0
  66. package/dist/types/OxyServices.d.ts +36 -3
  67. package/dist/types/crypto/index.d.ts +1 -1
  68. package/dist/types/crypto/keyManager.d.ts +110 -9
  69. package/dist/types/crypto/polyfill.d.ts +3 -1
  70. package/dist/types/crypto/recoveryPhrase.d.ts +31 -7
  71. package/dist/types/crypto/signatureService.d.ts +4 -0
  72. package/dist/types/index.d.ts +4 -3
  73. package/dist/types/mixins/OxyServices.analytics.d.ts +1 -0
  74. package/dist/types/mixins/OxyServices.assets.d.ts +6 -10
  75. package/dist/types/mixins/OxyServices.auth.d.ts +16 -0
  76. package/dist/types/mixins/OxyServices.contacts.d.ts +99 -0
  77. package/dist/types/mixins/OxyServices.developer.d.ts +1 -0
  78. package/dist/types/mixins/OxyServices.devices.d.ts +1 -0
  79. package/dist/types/mixins/OxyServices.features.d.ts +2 -7
  80. package/dist/types/mixins/OxyServices.fedcm.d.ts +1 -0
  81. package/dist/types/mixins/OxyServices.karma.d.ts +1 -0
  82. package/dist/types/mixins/OxyServices.language.d.ts +1 -0
  83. package/dist/types/mixins/OxyServices.location.d.ts +1 -0
  84. package/dist/types/mixins/OxyServices.managedAccounts.d.ts +1 -0
  85. package/dist/types/mixins/OxyServices.payment.d.ts +1 -0
  86. package/dist/types/mixins/OxyServices.popup.d.ts +1 -0
  87. package/dist/types/mixins/OxyServices.privacy.d.ts +1 -0
  88. package/dist/types/mixins/OxyServices.redirect.d.ts +1 -0
  89. package/dist/types/mixins/OxyServices.security.d.ts +1 -0
  90. package/dist/types/mixins/OxyServices.topics.d.ts +1 -0
  91. package/dist/types/mixins/OxyServices.user.d.ts +40 -11
  92. package/dist/types/mixins/OxyServices.utility.d.ts +1 -0
  93. package/dist/types/mixins/index.d.ts +52 -4
  94. package/dist/types/models/interfaces.d.ts +62 -3
  95. package/dist/types/utils/accountUtils.d.ts +41 -1
  96. package/dist/types/utils/asyncUtils.d.ts +6 -2
  97. package/dist/types/utils/platformCrypto.d.ts +87 -0
  98. package/dist/types/utils/platformCrypto.native.d.ts +54 -0
  99. package/package.json +28 -1
  100. package/src/CrossDomainAuth.ts +12 -10
  101. package/src/HttpService.ts +264 -51
  102. package/src/OxyServices.base.ts +10 -0
  103. package/src/OxyServices.ts +9 -4
  104. package/src/crypto/__tests__/keyManager.test.ts +336 -0
  105. package/src/crypto/index.ts +6 -1
  106. package/src/crypto/keyManager.ts +529 -151
  107. package/src/crypto/polyfill.ts +14 -34
  108. package/src/crypto/recoveryPhrase.ts +56 -17
  109. package/src/crypto/signatureService.ts +25 -29
  110. package/src/i18n/locales/en-US.json +46 -1
  111. package/src/i18n/locales/es-ES.json +46 -1
  112. package/src/index.ts +16 -3
  113. package/src/mixins/OxyServices.assets.ts +15 -11
  114. package/src/mixins/OxyServices.auth.ts +28 -0
  115. package/src/mixins/OxyServices.contacts.ts +73 -0
  116. package/src/mixins/OxyServices.features.ts +2 -12
  117. package/src/mixins/OxyServices.fedcm.ts +4 -3
  118. package/src/mixins/OxyServices.language.ts +6 -4
  119. package/src/mixins/OxyServices.redirect.ts +6 -2
  120. package/src/mixins/OxyServices.security.ts +18 -8
  121. package/src/mixins/OxyServices.user.ts +90 -49
  122. package/src/mixins/OxyServices.utility.ts +19 -10
  123. package/src/mixins/index.ts +58 -7
  124. package/src/models/interfaces.ts +65 -3
  125. package/src/utils/__tests__/asyncUtils.test.ts +187 -0
  126. package/src/utils/accountUtils.ts +82 -2
  127. package/src/utils/asyncUtils.ts +39 -9
  128. package/src/utils/deviceManager.ts +7 -4
  129. package/src/utils/platformCrypto.native.ts +101 -0
  130. package/src/utils/platformCrypto.ts +145 -0
@@ -4,7 +4,76 @@
4
4
  * Used by both @oxyhq/services (React Native) and @oxyhq/auth (Web) account stores.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.createQuickAccount = exports.buildAccountsArray = void 0;
7
+ exports.createQuickAccount = exports.buildAccountsArray = exports.getAccountFallbackHandle = exports.getAccountDisplayName = exports.formatPublicKeyHandle = void 0;
8
+ const i18n_1 = require("../i18n");
9
+ /**
10
+ * Truncate a long public key for display, e.g. `0x12345678…`.
11
+ * Falls back to the raw key if it's too short to truncate.
12
+ */
13
+ const formatPublicKeyHandle = (publicKey) => {
14
+ const cleaned = publicKey.startsWith('0x') ? publicKey.slice(2) : publicKey;
15
+ if (cleaned.length <= 8)
16
+ return `0x${cleaned}`;
17
+ return `0x${cleaned.slice(0, 8)}…`;
18
+ };
19
+ exports.formatPublicKeyHandle = formatPublicKeyHandle;
20
+ /**
21
+ * Resolve a friendly display name for a user.
22
+ *
23
+ * Order of preference:
24
+ * 1. `name.full`, or composed `name.first name.last`
25
+ * 2. `name` (when stored as a plain string)
26
+ * 3. `username`
27
+ * 4. `Account 0x12345678…` (derived from publicKey, when present)
28
+ * 5. Translated fallback (e.g. "Unnamed")
29
+ *
30
+ * The translation key `common.unnamed` is used for the final fallback. If the
31
+ * caller does not pass a locale, the default English translation is used.
32
+ */
33
+ const getAccountDisplayName = (user, locale) => {
34
+ if (!user)
35
+ return (0, i18n_1.translate)(locale, 'common.unnamed');
36
+ const { name, username, publicKey } = user;
37
+ if (name && typeof name === 'object') {
38
+ if (typeof name.full === 'string' && name.full.trim())
39
+ return name.full.trim();
40
+ const first = typeof name.first === 'string' ? name.first.trim() : '';
41
+ const last = typeof name.last === 'string' ? name.last.trim() : '';
42
+ const composed = [first, last].filter(Boolean).join(' ').trim();
43
+ if (composed)
44
+ return composed;
45
+ }
46
+ else if (typeof name === 'string' && name.trim()) {
47
+ return name.trim();
48
+ }
49
+ if (typeof username === 'string' && username.trim())
50
+ return username.trim();
51
+ if (typeof publicKey === 'string' && publicKey.length > 0) {
52
+ return (0, i18n_1.translate)(locale, 'common.accountFallback', {
53
+ handle: (0, exports.formatPublicKeyHandle)(publicKey),
54
+ });
55
+ }
56
+ return (0, i18n_1.translate)(locale, 'common.unnamed');
57
+ };
58
+ exports.getAccountDisplayName = getAccountDisplayName;
59
+ /**
60
+ * Resolve a `@handle` style identifier for a user.
61
+ *
62
+ * Returns the bare username when present (without the `@`), otherwise a
63
+ * truncated public-key handle (`0x12345678…`), or `undefined` when neither is
64
+ * available — callers can decide whether to hide the line entirely.
65
+ */
66
+ const getAccountFallbackHandle = (user) => {
67
+ if (!user)
68
+ return undefined;
69
+ if (typeof user.username === 'string' && user.username.trim())
70
+ return user.username.trim();
71
+ if (typeof user.publicKey === 'string' && user.publicKey.length > 0) {
72
+ return (0, exports.formatPublicKeyHandle)(user.publicKey);
73
+ }
74
+ return undefined;
75
+ };
76
+ exports.getAccountFallbackHandle = getAccountFallbackHandle;
8
77
  /**
9
78
  * Build an ordered array of QuickAccounts from a map and order list.
10
79
  */
@@ -27,7 +96,7 @@ exports.buildAccountsArray = buildAccountsArray;
27
96
  * @param getFileDownloadUrl - Function to generate avatar download URL from file ID
28
97
  */
29
98
  const createQuickAccount = (sessionId, userData, existingAccount, getFileDownloadUrl) => {
30
- const displayName = userData.name?.full || userData.name?.first || userData.username || 'Account';
99
+ const displayName = (0, exports.getAccountDisplayName)(userData);
31
100
  const userId = userData.id || (typeof userData._id === 'string' ? userData._id : userData._id?.toString());
32
101
  // Preserve existing avatarUrl if avatar hasn't changed (prevents image reload)
33
102
  let avatarUrl;
@@ -44,18 +44,47 @@ async function parallelWithErrorHandling(operations, errorHandler) {
44
44
  const results = await Promise.allSettled(operations.map((op, index) => withErrorHandling(op, error => errorHandler?.(error, index))));
45
45
  return results.map(result => result.status === 'fulfilled' ? result.value : null);
46
46
  }
47
+ /**
48
+ * Extract an HTTP status code from an error value, tolerating both the
49
+ * axios-style nested shape (`error.response.status`) and the flat shape
50
+ * produced by {@link handleHttpError} / fetch-based clients (`error.status`).
51
+ *
52
+ * Centralising this lookup prevents retry predicates from silently falling
53
+ * through when one of the two shapes is missing, which previously caused
54
+ * @oxyhq/core to retry 4xx responses and turn sub-10ms failures into
55
+ * multi-second stalls for every missing-resource lookup.
56
+ */
57
+ function extractHttpStatus(error) {
58
+ if (!error || typeof error !== 'object')
59
+ return undefined;
60
+ const candidate = error;
61
+ const flat = candidate.status;
62
+ if (typeof flat === 'number' && Number.isFinite(flat))
63
+ return flat;
64
+ const nested = candidate.response?.status;
65
+ if (typeof nested === 'number' && Number.isFinite(nested))
66
+ return nested;
67
+ return undefined;
68
+ }
47
69
  /**
48
70
  * Retry an async operation with exponential backoff
49
71
  *
50
- * By default, does not retry on 4xx errors (client errors).
51
- * Use shouldRetry callback to customize retry behavior.
72
+ * By default, does not retry on 4xx errors (client errors). The default
73
+ * predicate accepts both the axios-style `error.response.status` and the
74
+ * flat `error.status` shape produced by {@link handleHttpError}, so callers
75
+ * never accidentally retry a deterministic client failure.
76
+ *
77
+ * Use the `shouldRetry` callback to customize retry behavior.
52
78
  */
53
79
  async function retryAsync(operation, maxRetries = 3, baseDelay = 1000, shouldRetry) {
54
80
  let lastError;
55
- // Default shouldRetry: don't retry on 4xx errors
81
+ // Default shouldRetry: don't retry on 4xx errors (client errors).
82
+ // Checks BOTH `error.status` (flat shape from handleHttpError / fetch
83
+ // clients) AND `error.response.status` (axios-style shape) so neither
84
+ // representation can leak a client error into the retry loop.
56
85
  const defaultShouldRetry = (error) => {
57
- // Don't retry on 4xx errors (client errors)
58
- if (error?.response?.status >= 400 && error?.response?.status < 500) {
86
+ const status = extractHttpStatus(error);
87
+ if (status !== undefined && status >= 400 && status < 500) {
59
88
  return false;
60
89
  }
61
90
  return true;
@@ -1,39 +1,7 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
3
  exports.DeviceManager = void 0;
4
+ const platformCrypto_1 = require("./platformCrypto");
37
5
  /**
38
6
  * Client-side device management utility
39
7
  * Handles persistent device identification across app sessions
@@ -51,9 +19,10 @@ class DeviceManager {
51
19
  static async getStorage() {
52
20
  if (this.isReactNative()) {
53
21
  try {
54
- // Variable indirection prevents bundlers (Vite, webpack) from statically resolving this
55
- const moduleName = '@react-native-async-storage/async-storage';
56
- const asyncStorageModule = await Promise.resolve(`${moduleName}`).then(s => __importStar(require(s)));
22
+ // `loadAsyncStorage` is per-platform: the RN variant statically imports
23
+ // @react-native-async-storage/async-storage, the default variant throws
24
+ // (never called outside RN because of the `isReactNative()` gate above).
25
+ const asyncStorageModule = await (0, platformCrypto_1.loadAsyncStorage)();
57
26
  const storage = asyncStorageModule.default;
58
27
  return {
59
28
  getItem: storage.getItem.bind(storage),
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ /**
3
+ * Platform Crypto / Storage — Default Variant (Node.js, Browser, generic bundlers)
4
+ *
5
+ * Provides lazy access to platform-specific crypto and storage modules.
6
+ *
7
+ * # Variants
8
+ *
9
+ * This module ships in two physical variants on disk, selected per consumer
10
+ * by the bundler / runtime:
11
+ *
12
+ * - `platformCrypto.js` — this file. Used by Node.js, Vite, webpack,
13
+ * Rollup, esbuild, and anything that does
14
+ * not match Metro's `*.native.js`
15
+ * source-extension preference.
16
+ * - `platformCrypto.native.js` — sibling file. Picked up automatically by
17
+ * Metro's resolver (which prefers
18
+ * `*.<platform>.js` and `*.native.js` over
19
+ * plain `*.js` when `preferNativePlatform`
20
+ * is true — Expo sets this for all non-web
21
+ * builds).
22
+ *
23
+ * The `package.json#exports` map also declares a `"react-native"` condition
24
+ * pointing at the same `dist/esm/index.js` entry — that entry transitively
25
+ * imports `./platformCrypto`, and Metro's per-file source-extension lookup
26
+ * substitutes the `.native.js` sibling automatically inside `dist/`. This
27
+ * means consumers never have to add resolver shims; Metro Just Works.
28
+ *
29
+ * Both variants expose the EXACT same public API; importers don't need to know
30
+ * which one they got. The variant difference is purely about which underlying
31
+ * native modules each one references:
32
+ *
33
+ * ┌──────────────────┬───────────────────────┬───────────────────────────────┐
34
+ * │ Function │ Default variant │ React Native variant │
35
+ * ├──────────────────┼───────────────────────┼───────────────────────────────┤
36
+ * │ loadNodeCrypto │ `await import('crypto')` (Node built-in) │
37
+ * │ │ │ throws — Node crypto is not │
38
+ * │ │ │ available on Hermes/RN │
39
+ * ├──────────────────┼───────────────────────┼───────────────────────────────┤
40
+ * │ loadExpoCrypto │ throws — expo-crypto │ static `import 'expo-crypto'` │
41
+ * │ │ is not part of a │ │
42
+ * │ │ Node/Vite bundle │ │
43
+ * ├──────────────────┼───────────────────────┼───────────────────────────────┤
44
+ * │ loadSecureStore │ throws (web/Node have │ static `import 'expo-secure-` │
45
+ * │ │ their own storage) │ store' │
46
+ * ├──────────────────┼───────────────────────┼───────────────────────────────┤
47
+ * │ loadAsyncStorage │ throws (web/Node have │ static `import '@react- │
48
+ * │ │ their own storage) │ native-async-storage/...' │
49
+ * ├──────────────────┼───────────────────────┼───────────────────────────────┤
50
+ * │ getRandomBytesRN │ throws (RN-only) │ direct call into expo-crypto │
51
+ * └──────────────────┴───────────────────────┴───────────────────────────────┘
52
+ *
53
+ * Crucially, the default variant references ONLY Node's `'crypto'`. It never
54
+ * mentions `expo-*` or `@react-native-async-storage/*` — so Vite, webpack,
55
+ * esbuild, Rollup, and Node itself can bundle / require it without ever
56
+ * attempting to resolve those RN-only packages.
57
+ *
58
+ * The React Native variant references ONLY the RN packages. It never
59
+ * mentions `'crypto'` — so Metro and Hermes have nothing to choke on.
60
+ *
61
+ * # Why not a single file with dynamic import?
62
+ *
63
+ * A previous iteration used a "bundler-opaque" `new Function('s', 'return
64
+ * import(s)')` trick so a single file could service every platform. It
65
+ * bundled cleanly on Metro but Hermes refused to PARSE the resulting
66
+ * `import()` expression inside a Function-constructor body
67
+ * (`SyntaxError: Invalid expression encountered` at the `(` of `import(`).
68
+ * The platform-extension split is the only approach that lets each runtime
69
+ * see a file containing only specifiers it can understand — no tricks, no
70
+ * runtime parsing risks.
71
+ */
72
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
73
+ if (k2 === undefined) k2 = k;
74
+ var desc = Object.getOwnPropertyDescriptor(m, k);
75
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
76
+ desc = { enumerable: true, get: function() { return m[k]; } };
77
+ }
78
+ Object.defineProperty(o, k2, desc);
79
+ }) : (function(o, m, k, k2) {
80
+ if (k2 === undefined) k2 = k;
81
+ o[k2] = m[k];
82
+ }));
83
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
84
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
85
+ }) : function(o, v) {
86
+ o["default"] = v;
87
+ });
88
+ var __importStar = (this && this.__importStar) || (function () {
89
+ var ownKeys = function(o) {
90
+ ownKeys = Object.getOwnPropertyNames || function (o) {
91
+ var ar = [];
92
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
93
+ return ar;
94
+ };
95
+ return ownKeys(o);
96
+ };
97
+ return function (mod) {
98
+ if (mod && mod.__esModule) return mod;
99
+ var result = {};
100
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
101
+ __setModuleDefault(result, mod);
102
+ return result;
103
+ };
104
+ })();
105
+ Object.defineProperty(exports, "__esModule", { value: true });
106
+ exports.loadNodeCrypto = loadNodeCrypto;
107
+ exports.loadExpoCrypto = loadExpoCrypto;
108
+ exports.loadSecureStore = loadSecureStore;
109
+ exports.loadAsyncStorage = loadAsyncStorage;
110
+ exports.getRandomBytesRN = getRandomBytesRN;
111
+ const platform_1 = require("./platform");
112
+ // ---------------------------------------------------------------------------
113
+ // Node `crypto` — Node built-in
114
+ //
115
+ // `await import('crypto')` here is a real, static-from-tsc's-perspective
116
+ // dynamic import. Node ESM, Vite, webpack, and esbuild all resolve it fine.
117
+ // Metro never sees this file because the `.react-native.js` sibling shadows
118
+ // it, so Metro never tries to resolve `'crypto'`.
119
+ // ---------------------------------------------------------------------------
120
+ let cachedNodeCrypto = null;
121
+ async function loadNodeCrypto() {
122
+ if (cachedNodeCrypto) {
123
+ return cachedNodeCrypto;
124
+ }
125
+ cachedNodeCrypto = await Promise.resolve().then(() => __importStar(require('node:crypto')));
126
+ return cachedNodeCrypto;
127
+ }
128
+ // ---------------------------------------------------------------------------
129
+ // RN-only modules — never called from this variant.
130
+ //
131
+ // These throw a clear error if anything ever reaches them outside RN. In
132
+ // practice every caller gates with `isReactNative()` before calling, so
133
+ // these are belt-and-braces.
134
+ // ---------------------------------------------------------------------------
135
+ function notReactNativeError(module) {
136
+ return new Error(`[oxy.platformCrypto] Tried to load '${module}' outside React Native. This module is only available in a React Native runtime; bundling routed this consumer to the default (Node/web) variant. This indicates a missing platform gate (\`isReactNative()\`) in the calling code.`);
137
+ }
138
+ async function loadExpoCrypto() {
139
+ if ((0, platform_1.isReactNative)()) {
140
+ // Should be unreachable: when running on RN, Metro / the `react-native`
141
+ // exports condition serves the sibling variant. If we got here, the
142
+ // package-exports map is misconfigured for this host. Throw with a
143
+ // helpful diagnostic rather than fall back to a broken dynamic import.
144
+ throw new Error('[oxy.platformCrypto] React Native runtime resolved the default ' +
145
+ '(non-RN) variant of @oxyhq/core/utils/platformCrypto. Check the ' +
146
+ "consumer's bundler resolution — Metro should pick the sibling " +
147
+ '.react-native.js file via package exports.');
148
+ }
149
+ throw notReactNativeError('expo-crypto');
150
+ }
151
+ async function loadSecureStore() {
152
+ throw notReactNativeError('expo-secure-store');
153
+ }
154
+ async function loadAsyncStorage() {
155
+ throw notReactNativeError('@react-native-async-storage/async-storage');
156
+ }
157
+ /**
158
+ * Synchronous random-bytes via `expo-crypto.getRandomBytes`. Only available
159
+ * in the React Native variant. The default variant throws because Node and
160
+ * browsers have their own native CSPRNGs (`crypto.randomBytes` and
161
+ * `crypto.getRandomValues` respectively) — callers should use those.
162
+ */
163
+ function getRandomBytesRN(_byteCount) {
164
+ throw notReactNativeError('expo-crypto.getRandomBytes (sync)');
165
+ }
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ /**
3
+ * Platform Crypto / Storage — React Native Variant
4
+ *
5
+ * Companion to `./platformCrypto.ts`. See the doc-comment at the top of that
6
+ * file for the full design.
7
+ *
8
+ * Metro auto-selects this file in any non-web build (`preferNativePlatform`
9
+ * is `true` for iOS / Android, so `*.native.js` shadows `*.js` during
10
+ * source-extension resolution inside `node_modules/@oxyhq/core/dist/`). On
11
+ * iOS / Android `<base>.ios.js` / `<base>.android.js` would shadow this file
12
+ * if they existed, but they don't — `.native.js` is the shared RN variant.
13
+ *
14
+ * - The default variant references Node's `'crypto'` and would crash Metro
15
+ * if bundled into an RN app.
16
+ * - This variant references the RN-only modules (`expo-crypto`,
17
+ * `expo-secure-store`, `@react-native-async-storage/async-storage`)
18
+ * as static imports, so Metro and Hermes both resolve and parse them
19
+ * cleanly.
20
+ *
21
+ * Both variants expose the same surface; importers don't care which one
22
+ * they got.
23
+ *
24
+ * # Why static imports?
25
+ *
26
+ * Every RN consumer of `@oxyhq/core` already lists or transitively pulls
27
+ * in `expo-crypto`, `expo-secure-store`, and
28
+ * `@react-native-async-storage/async-storage` (they're stable Expo modules
29
+ * present in `services`, `accounts`, `inbox`, and `test-app`). A static
30
+ * import is what Metro wants to see anyway, and Hermes parses it like any
31
+ * other ES module — no `Function`-constructor parser exotic-mode involved.
32
+ *
33
+ * This is also clearer to debug: Metro fails up-front with a normal
34
+ * unresolved-module error if a consumer is missing a peer dep, instead of
35
+ * a confusing runtime throw the first time a code path that needs the
36
+ * module is exercised.
37
+ */
38
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
39
+ if (k2 === undefined) k2 = k;
40
+ var desc = Object.getOwnPropertyDescriptor(m, k);
41
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
42
+ desc = { enumerable: true, get: function() { return m[k]; } };
43
+ }
44
+ Object.defineProperty(o, k2, desc);
45
+ }) : (function(o, m, k, k2) {
46
+ if (k2 === undefined) k2 = k;
47
+ o[k2] = m[k];
48
+ }));
49
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
50
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
51
+ }) : function(o, v) {
52
+ o["default"] = v;
53
+ });
54
+ var __importStar = (this && this.__importStar) || (function () {
55
+ var ownKeys = function(o) {
56
+ ownKeys = Object.getOwnPropertyNames || function (o) {
57
+ var ar = [];
58
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
59
+ return ar;
60
+ };
61
+ return ownKeys(o);
62
+ };
63
+ return function (mod) {
64
+ if (mod && mod.__esModule) return mod;
65
+ var result = {};
66
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
67
+ __setModuleDefault(result, mod);
68
+ return result;
69
+ };
70
+ })();
71
+ var __importDefault = (this && this.__importDefault) || function (mod) {
72
+ return (mod && mod.__esModule) ? mod : { "default": mod };
73
+ };
74
+ Object.defineProperty(exports, "__esModule", { value: true });
75
+ exports.loadNodeCrypto = loadNodeCrypto;
76
+ exports.loadExpoCrypto = loadExpoCrypto;
77
+ exports.loadSecureStore = loadSecureStore;
78
+ exports.loadAsyncStorage = loadAsyncStorage;
79
+ exports.getRandomBytesRN = getRandomBytesRN;
80
+ const ExpoCrypto = __importStar(require("expo-crypto"));
81
+ const SecureStore = __importStar(require("expo-secure-store"));
82
+ const async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
83
+ // ---------------------------------------------------------------------------
84
+ // Node `crypto` — never available in RN.
85
+ // ---------------------------------------------------------------------------
86
+ async function loadNodeCrypto() {
87
+ // Unreachable in practice: every caller gates with `isNodeJS()` before
88
+ // invoking this. If it somehow does fire, throw immediately with a clear
89
+ // diagnostic rather than letting Metro / Hermes attempt to find a
90
+ // non-existent module at runtime.
91
+ throw new Error("[oxy.platformCrypto] Node's built-in 'crypto' module is not available " +
92
+ 'in a React Native runtime. Use the RN-specific helpers ' +
93
+ '(loadExpoCrypto, getRandomBytesRN) or the Web Crypto API (`globalThis.crypto`).');
94
+ }
95
+ // ---------------------------------------------------------------------------
96
+ // expo-crypto — RN cryptographic primitives.
97
+ // ---------------------------------------------------------------------------
98
+ async function loadExpoCrypto() {
99
+ return ExpoCrypto;
100
+ }
101
+ // ---------------------------------------------------------------------------
102
+ // expo-secure-store — RN keychain / keystore.
103
+ // ---------------------------------------------------------------------------
104
+ async function loadSecureStore() {
105
+ return SecureStore;
106
+ }
107
+ async function loadAsyncStorage() {
108
+ // Mirror the shape callers historically used (`module.default.<method>`)
109
+ // so the call sites don't have to know whether the underlying module
110
+ // ships ESM or CJS-with-default.
111
+ const storage = async_storage_1.default;
112
+ return {
113
+ default: storage,
114
+ };
115
+ }
116
+ /**
117
+ * Synchronous random-bytes via `expo-crypto.getRandomBytes`. Available
118
+ * synchronously because `expo-crypto` is statically imported by this file
119
+ * — no async initialization race.
120
+ */
121
+ function getRandomBytesRN(byteCount) {
122
+ return ExpoCrypto.getRandomBytes(byteCount);
123
+ }