@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
@@ -174,6 +174,7 @@ export declare function OxyServicesFedCMMixin<T extends typeof OxyServicesBase>(
174
174
  };
175
175
  clearCache(): void;
176
176
  clearCacheEntry(key: string): void;
177
+ clearCacheByPrefix(prefix: string): number;
177
178
  getCacheStats(): {
178
179
  size: number;
179
180
  hits: number;
@@ -55,6 +55,7 @@ export declare function OxyServicesKarmaMixin<T extends typeof OxyServicesBase>(
55
55
  };
56
56
  clearCache(): void;
57
57
  clearCacheEntry(key: string): void;
58
+ clearCacheByPrefix(prefix: string): number;
58
59
  getCacheStats(): {
59
60
  size: number;
60
61
  hits: number;
@@ -51,6 +51,7 @@ export declare function OxyServicesLanguageMixin<T extends typeof OxyServicesBas
51
51
  };
52
52
  clearCache(): void;
53
53
  clearCacheEntry(key: string): void;
54
+ clearCacheByPrefix(prefix: string): number;
54
55
  getCacheStats(): {
55
56
  size: number;
56
57
  hits: number;
@@ -34,6 +34,7 @@ export declare function OxyServicesLocationMixin<T extends typeof OxyServicesBas
34
34
  };
35
35
  clearCache(): void;
36
36
  clearCacheEntry(key: string): void;
37
+ clearCacheByPrefix(prefix: string): number;
37
38
  getCacheStats(): {
38
39
  size: number;
39
40
  hits: number;
@@ -91,6 +91,7 @@ export declare function OxyServicesManagedAccountsMixin<T extends typeof OxyServ
91
91
  };
92
92
  clearCache(): void;
93
93
  clearCacheEntry(key: string): void;
94
+ clearCacheByPrefix(prefix: string): number;
94
95
  getCacheStats(): {
95
96
  size: number;
96
97
  hits: number;
@@ -81,6 +81,7 @@ export declare function OxyServicesPaymentMixin<T extends typeof OxyServicesBase
81
81
  };
82
82
  clearCache(): void;
83
83
  clearCacheEntry(key: string): void;
84
+ clearCacheByPrefix(prefix: string): number;
84
85
  getCacheStats(): {
85
86
  size: number;
86
87
  hits: number;
@@ -171,6 +171,7 @@ export declare function OxyServicesPopupAuthMixin<T extends typeof OxyServicesBa
171
171
  };
172
172
  clearCache(): void;
173
173
  clearCacheEntry(key: string): void;
174
+ clearCacheByPrefix(prefix: string): number;
174
175
  getCacheStats(): {
175
176
  size: number;
176
177
  hits: number;
@@ -92,6 +92,7 @@ export declare function OxyServicesPrivacyMixin<T extends typeof OxyServicesBase
92
92
  };
93
93
  clearCache(): void;
94
94
  clearCacheEntry(key: string): void;
95
+ clearCacheByPrefix(prefix: string): number;
95
96
  getCacheStats(): {
96
97
  size: number;
97
98
  hits: number;
@@ -208,6 +208,7 @@ export declare function OxyServicesRedirectAuthMixin<T extends typeof OxyService
208
208
  };
209
209
  clearCache(): void;
210
210
  clearCacheEntry(key: string): void;
211
+ clearCacheByPrefix(prefix: string): number;
211
212
  getCacheStats(): {
212
213
  size: number;
213
214
  hits: number;
@@ -48,6 +48,7 @@ export declare function OxyServicesSecurityMixin<T extends typeof OxyServicesBas
48
48
  };
49
49
  clearCache(): void;
50
50
  clearCacheEntry(key: string): void;
51
+ clearCacheByPrefix(prefix: string): number;
51
52
  getCacheStats(): {
52
53
  size: number;
53
54
  hits: number;
@@ -74,6 +74,7 @@ export declare function OxyServicesTopicsMixin<T extends typeof OxyServicesBase>
74
74
  };
75
75
  clearCache(): void;
76
76
  clearCacheEntry(key: string): void;
77
+ clearCacheByPrefix(prefix: string): number;
77
78
  getCacheStats(): {
78
79
  size: number;
79
80
  hits: number;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * User Management Methods Mixin
3
3
  */
4
- import type { User, Notification, SearchProfilesResponse } from '../models/interfaces';
4
+ import type { User, Notification, SearchProfilesResponse, PrivacySettings } from '../models/interfaces';
5
5
  import type { OxyServicesBase } from '../OxyServices.base';
6
6
  import { type PaginationParams } from '../utils/apiUtils';
7
7
  export declare function OxyServicesUserMixin<T extends typeof OxyServicesBase>(Base: T): {
@@ -10,6 +10,18 @@ export declare function OxyServicesUserMixin<T extends typeof OxyServicesBase>(B
10
10
  * Get profile by username
11
11
  */
12
12
  getProfileByUsername(username: string): Promise<User>;
13
+ /**
14
+ * Lightweight username lookup for login flows.
15
+ * Returns minimal public info: exists, color, avatar, displayName.
16
+ * Faster than getProfileByUsername — no stats, no formatting.
17
+ */
18
+ lookupUsername(username: string): Promise<{
19
+ exists: boolean;
20
+ username: string;
21
+ color: string | null;
22
+ avatar: string | null;
23
+ displayName: string;
24
+ }>;
13
25
  /**
14
26
  * Search user profiles
15
27
  */
@@ -80,21 +92,30 @@ export declare function OxyServicesUserMixin<T extends typeof OxyServicesBase>(B
80
92
  */
81
93
  getCurrentUser(): Promise<User>;
82
94
  /**
83
- * Update user profile
84
- * TanStack Query handles offline queuing automatically
95
+ * Update user profile.
96
+ *
97
+ * Invalidates the SDK-side response cache for every endpoint that
98
+ * returns the current user (`GET /users/me`, `GET /session/user/*`,
99
+ * `GET /users/<id>`, `GET /profiles/username/*`) so the next read
100
+ * doesn't return a stale snapshot. Without this, a follow-up
101
+ * `getUserBySession` call inside the 2-minute cache window can return
102
+ * the pre-update user — most visibly during onboarding, where it
103
+ * causes the username step to flicker back as if nothing was saved.
104
+ *
105
+ * TanStack Query handles offline queuing automatically.
85
106
  */
86
- updateProfile(updates: Record<string, any>): Promise<User>;
107
+ updateProfile(updates: Partial<User>): Promise<User>;
87
108
  /**
88
109
  * Get privacy settings for a user
89
110
  * @param userId - The user ID (defaults to current user)
90
111
  */
91
- getPrivacySettings(userId?: string): Promise<any>;
112
+ getPrivacySettings(userId?: string): Promise<PrivacySettings>;
92
113
  /**
93
114
  * Update privacy settings
94
115
  * @param settings - Partial privacy settings object
95
116
  * @param userId - The user ID (defaults to current user)
96
117
  */
97
- updatePrivacySettings(settings: Record<string, any>, userId?: string): Promise<any>;
118
+ updatePrivacySettings(settings: Partial<PrivacySettings>, userId?: string): Promise<PrivacySettings>;
98
119
  /**
99
120
  * Request account verification
100
121
  */
@@ -107,11 +128,18 @@ export declare function OxyServicesUserMixin<T extends typeof OxyServicesBase>(B
107
128
  */
108
129
  downloadAccountData(format?: "json" | "csv"): Promise<Blob>;
109
130
  /**
110
- * Delete account permanently
111
- * @param password - User password for confirmation
112
- * @param confirmText - Confirmation text (usually username)
113
- */
114
- deleteAccount(password: string, confirmText: string): Promise<{
131
+ * Delete account permanently.
132
+ *
133
+ * Signs `delete:{publicKey}:{timestamp}` with the locally-stored identity
134
+ * private key and submits the signature alongside the confirmation text
135
+ * (must equal the user's username). The signature is the cryptographic
136
+ * proof of ownership — only the device holding the private key can issue
137
+ * a valid signature, so no password is required.
138
+ *
139
+ * @param confirmText - Must equal the user's username (verified server-side)
140
+ * @throws If no identity is stored on this device, or signing fails
141
+ */
142
+ deleteAccount(confirmText: string): Promise<{
115
143
  message: string;
116
144
  }>;
117
145
  /**
@@ -191,6 +219,7 @@ export declare function OxyServicesUserMixin<T extends typeof OxyServicesBase>(B
191
219
  };
192
220
  clearCache(): void;
193
221
  clearCacheEntry(key: string): void;
222
+ clearCacheByPrefix(prefix: string): number;
194
223
  getCacheStats(): {
195
224
  size: number;
196
225
  hits: number;
@@ -163,6 +163,7 @@ export declare function OxyServicesUtilityMixin<T extends typeof OxyServicesBase
163
163
  };
164
164
  clearCache(): void;
165
165
  clearCacheEntry(key: string): void;
166
+ clearCacheByPrefix(prefix: string): number;
166
167
  getCacheStats(): {
167
168
  size: number;
168
169
  hits: number;
@@ -4,7 +4,50 @@
4
4
  * This module provides a clean way to compose all mixins
5
5
  * and ensures consistent ordering for better maintainability
6
6
  */
7
- type MixinFunction = (Base: any) => any;
7
+ import { OxyServicesBase } from '../OxyServices.base';
8
+ import { OxyServicesAuthMixin } from './OxyServices.auth';
9
+ import { OxyServicesFedCMMixin } from './OxyServices.fedcm';
10
+ import { OxyServicesPopupAuthMixin } from './OxyServices.popup';
11
+ import { OxyServicesRedirectAuthMixin } from './OxyServices.redirect';
12
+ import { OxyServicesUserMixin } from './OxyServices.user';
13
+ import { OxyServicesPrivacyMixin } from './OxyServices.privacy';
14
+ import { OxyServicesLanguageMixin } from './OxyServices.language';
15
+ import { OxyServicesPaymentMixin } from './OxyServices.payment';
16
+ import { OxyServicesKarmaMixin } from './OxyServices.karma';
17
+ import { OxyServicesAssetsMixin } from './OxyServices.assets';
18
+ import { OxyServicesDeveloperMixin } from './OxyServices.developer';
19
+ import { OxyServicesLocationMixin } from './OxyServices.location';
20
+ import { OxyServicesAnalyticsMixin } from './OxyServices.analytics';
21
+ import { OxyServicesDevicesMixin } from './OxyServices.devices';
22
+ import { OxyServicesSecurityMixin } from './OxyServices.security';
23
+ import { OxyServicesUtilityMixin } from './OxyServices.utility';
24
+ import { OxyServicesFeaturesMixin } from './OxyServices.features';
25
+ import { OxyServicesTopicsMixin } from './OxyServices.topics';
26
+ import { OxyServicesManagedAccountsMixin } from './OxyServices.managedAccounts';
27
+ import { OxyServicesContactsMixin } from './OxyServices.contacts';
28
+ /**
29
+ * Instance shape of every mixin in the pipeline, intersected. The runtime
30
+ * `composeOxyServices()` produces a class whose instances expose all of
31
+ * these methods; we surface that to TypeScript via this intersection so the
32
+ * `extends` site in `OxyServices.ts` can avoid an `as any` cast.
33
+ *
34
+ * If you add a new mixin to `MIXIN_PIPELINE`, add it here too so its methods
35
+ * are visible without a cast.
36
+ */
37
+ type AllMixinInstances = InstanceType<ReturnType<typeof OxyServicesAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesFedCMMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPopupAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesRedirectAuthMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesUserMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPrivacyMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesLanguageMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesPaymentMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesKarmaMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAssetsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesDeveloperMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesLocationMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesAnalyticsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesDevicesMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesSecurityMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesFeaturesMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesTopicsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesManagedAccountsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesContactsMixin<typeof OxyServicesBase>>> & InstanceType<ReturnType<typeof OxyServicesUtilityMixin<typeof OxyServicesBase>>>;
38
+ /**
39
+ * Constructor type for the fully composed mixin pipeline. Each mixin returns
40
+ * a new constructor that augments its input; reducing across the pipeline
41
+ * yields an instance with every mixin's methods.
42
+ */
43
+ export type ComposedOxyServicesConstructor = new (config: import('../OxyServices.base').OxyConfig) => AllMixinInstances;
44
+ /**
45
+ * A mixin function: takes a constructor and returns an augmented constructor.
46
+ * Each individual mixin uses a `<T extends typeof OxyServicesBase>` generic
47
+ * to preserve its specific augmentations, but those refinements are
48
+ * intentionally collapsed across the `reduce` call below.
49
+ */
50
+ type MixinFunction = (Base: new (...args: unknown[]) => OxyServicesBase) => new (...args: unknown[]) => OxyServicesBase;
8
51
  /**
9
52
  * Mixin pipeline - applied in order from first to last.
10
53
  *
@@ -22,9 +65,14 @@ declare const MIXIN_PIPELINE: MixinFunction[];
22
65
  * Composes all OxyServices mixins using a pipeline pattern.
23
66
  *
24
67
  * This is equivalent to the nested calls but more readable and maintainable.
25
- * Adding a new mixin: just add it to MIXIN_PIPELINE at the appropriate position.
68
+ * Adding a new mixin: add it to MIXIN_PIPELINE at the appropriate position
69
+ * AND extend `AllMixinInstances` so its methods are visible to consumers.
70
+ *
71
+ * The cast through `unknown` carries the runtime augmentation chain into the
72
+ * static type system. `Array.reduce` cannot track each mixin's generic
73
+ * refinement, so we assert the final shape exposed by all mixins together.
26
74
  *
27
- * @returns The fully composed OxyServices class with all mixins applied
75
+ * @returns The fully composed OxyServices constructor with all mixins applied
28
76
  */
29
- export declare function composeOxyServices(): any;
77
+ export declare function composeOxyServices(): ComposedOxyServicesConstructor;
30
78
  export { MIXIN_PIPELINE };
@@ -18,6 +18,40 @@ export interface OxyConfig {
18
18
  onRequestEnd?: (url: string, method: string, duration: number, success: boolean) => void;
19
19
  onRequestError?: (url: string, method: string, error: Error) => void;
20
20
  }
21
+ /**
22
+ * Privacy settings for a user account.
23
+ *
24
+ * All fields are optional because:
25
+ * - Updates are dot-path partial PATCHes — clients send only changed keys.
26
+ * - The server may return a partial subdocument depending on the API
27
+ * build (older builds returned only the field that changed).
28
+ * - User accounts created before a new toggle was introduced won't
29
+ * have that key persisted yet.
30
+ *
31
+ * Mirrors `IPrivacySettings` from `packages/api/src/types/privacy.types.ts`,
32
+ * but with every field marked optional.
33
+ */
34
+ export interface PrivacySettings {
35
+ isPrivateAccount?: boolean;
36
+ hideOnlineStatus?: boolean;
37
+ hideLastSeen?: boolean;
38
+ profileVisibility?: boolean;
39
+ loginAlerts?: boolean;
40
+ blockScreenshots?: boolean;
41
+ login?: boolean;
42
+ biometricLogin?: boolean;
43
+ showActivity?: boolean;
44
+ allowTagging?: boolean;
45
+ allowMentions?: boolean;
46
+ hideReadReceipts?: boolean;
47
+ allowDirectMessages?: boolean;
48
+ dataSharing?: boolean;
49
+ locationSharing?: boolean;
50
+ analyticsSharing?: boolean;
51
+ sensitiveContent?: boolean;
52
+ autoFilter?: boolean;
53
+ muteKeywords?: boolean;
54
+ }
21
55
  export interface User {
22
56
  id: string;
23
57
  publicKey: string;
@@ -25,9 +59,7 @@ export interface User {
25
59
  email?: string;
26
60
  avatar?: string;
27
61
  color?: string;
28
- privacySettings?: {
29
- [key: string]: unknown;
30
- };
62
+ privacySettings?: PrivacySettings;
31
63
  name?: {
32
64
  first?: string;
33
65
  last?: string;
@@ -240,6 +272,33 @@ export interface FileDeleteResponse {
240
272
  message: string;
241
273
  fileId: string;
242
274
  }
275
+ /**
276
+ * React Native file descriptor accepted by FormData.
277
+ *
278
+ * On React Native, the multipart upload reads the file from disk via the URI
279
+ * during the network request — no in-JS Blob construction is required (and
280
+ * doing so would fail on Hermes since RN's BlobManager cannot wrap an
281
+ * ArrayBuffer/ArrayBufferView).
282
+ *
283
+ * This shape matches what `expo-document-picker` and `expo-image-picker`
284
+ * return for selected assets, and is what `OxyServices.assetUpload` accepts
285
+ * on native platforms.
286
+ */
287
+ export interface RNFileDescriptor {
288
+ uri: string;
289
+ type?: string;
290
+ name?: string;
291
+ size?: number;
292
+ }
293
+ /**
294
+ * Asset upload input — accepted by `OxyServices.assetUpload` and `uploadRawFile`.
295
+ *
296
+ * - `File` / `Blob`: standard web browser path. `assetUpload` appends the
297
+ * Blob to FormData directly.
298
+ * - {@link RNFileDescriptor}: React Native path. FormData reads the file from
299
+ * disk via the URI during the multipart request.
300
+ */
301
+ export type AssetUploadInput = File | Blob | RNFileDescriptor;
243
302
  /**
244
303
  * Central Asset Service interfaces
245
304
  */
@@ -10,6 +10,44 @@ export interface QuickAccount {
10
10
  avatar?: string;
11
11
  avatarUrl?: string;
12
12
  }
13
+ /** Minimal user shape accepted by display-name helpers. Avoids importing the full User type. */
14
+ export interface DisplayNameUserShape {
15
+ name?: string | {
16
+ first?: string;
17
+ last?: string;
18
+ full?: string;
19
+ [key: string]: unknown;
20
+ };
21
+ username?: string;
22
+ publicKey?: string;
23
+ }
24
+ /**
25
+ * Truncate a long public key for display, e.g. `0x12345678…`.
26
+ * Falls back to the raw key if it's too short to truncate.
27
+ */
28
+ export declare const formatPublicKeyHandle: (publicKey: string) => string;
29
+ /**
30
+ * Resolve a friendly display name for a user.
31
+ *
32
+ * Order of preference:
33
+ * 1. `name.full`, or composed `name.first name.last`
34
+ * 2. `name` (when stored as a plain string)
35
+ * 3. `username`
36
+ * 4. `Account 0x12345678…` (derived from publicKey, when present)
37
+ * 5. Translated fallback (e.g. "Unnamed")
38
+ *
39
+ * The translation key `common.unnamed` is used for the final fallback. If the
40
+ * caller does not pass a locale, the default English translation is used.
41
+ */
42
+ export declare const getAccountDisplayName: (user: DisplayNameUserShape | null | undefined, locale?: string) => string;
43
+ /**
44
+ * Resolve a `@handle` style identifier for a user.
45
+ *
46
+ * Returns the bare username when present (without the `@`), otherwise a
47
+ * truncated public-key handle (`0x12345678…`), or `undefined` when neither is
48
+ * available — callers can decide whether to hide the line entirely.
49
+ */
50
+ export declare const getAccountFallbackHandle: (user: DisplayNameUserShape | null | undefined) => string | undefined;
13
51
  /**
14
52
  * Build an ordered array of QuickAccounts from a map and order list.
15
53
  */
@@ -23,11 +61,13 @@ export declare const buildAccountsArray: (accounts: Record<string, QuickAccount>
23
61
  * @param getFileDownloadUrl - Function to generate avatar download URL from file ID
24
62
  */
25
63
  export declare const createQuickAccount: (sessionId: string, userData: {
26
- name?: {
64
+ name?: string | {
27
65
  full?: string;
28
66
  first?: string;
67
+ last?: string;
29
68
  };
30
69
  username?: string;
70
+ publicKey?: string;
31
71
  id?: string;
32
72
  _id?: {
33
73
  toString(): string;
@@ -13,8 +13,12 @@ export declare function parallelWithErrorHandling<T>(operations: (() => Promise<
13
13
  /**
14
14
  * Retry an async operation with exponential backoff
15
15
  *
16
- * By default, does not retry on 4xx errors (client errors).
17
- * Use shouldRetry callback to customize retry behavior.
16
+ * By default, does not retry on 4xx errors (client errors). The default
17
+ * predicate accepts both the axios-style `error.response.status` and the
18
+ * flat `error.status` shape produced by {@link handleHttpError}, so callers
19
+ * never accidentally retry a deterministic client failure.
20
+ *
21
+ * Use the `shouldRetry` callback to customize retry behavior.
18
22
  */
19
23
  export declare function retryAsync<T>(operation: () => Promise<T>, maxRetries?: number, baseDelay?: number, shouldRetry?: (error: any) => boolean): Promise<T>;
20
24
  /**
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Platform Crypto / Storage — Default Variant (Node.js, Browser, generic bundlers)
3
+ *
4
+ * Provides lazy access to platform-specific crypto and storage modules.
5
+ *
6
+ * # Variants
7
+ *
8
+ * This module ships in two physical variants on disk, selected per consumer
9
+ * by the bundler / runtime:
10
+ *
11
+ * - `platformCrypto.js` — this file. Used by Node.js, Vite, webpack,
12
+ * Rollup, esbuild, and anything that does
13
+ * not match Metro's `*.native.js`
14
+ * source-extension preference.
15
+ * - `platformCrypto.native.js` — sibling file. Picked up automatically by
16
+ * Metro's resolver (which prefers
17
+ * `*.<platform>.js` and `*.native.js` over
18
+ * plain `*.js` when `preferNativePlatform`
19
+ * is true — Expo sets this for all non-web
20
+ * builds).
21
+ *
22
+ * The `package.json#exports` map also declares a `"react-native"` condition
23
+ * pointing at the same `dist/esm/index.js` entry — that entry transitively
24
+ * imports `./platformCrypto`, and Metro's per-file source-extension lookup
25
+ * substitutes the `.native.js` sibling automatically inside `dist/`. This
26
+ * means consumers never have to add resolver shims; Metro Just Works.
27
+ *
28
+ * Both variants expose the EXACT same public API; importers don't need to know
29
+ * which one they got. The variant difference is purely about which underlying
30
+ * native modules each one references:
31
+ *
32
+ * ┌──────────────────┬───────────────────────┬───────────────────────────────┐
33
+ * │ Function │ Default variant │ React Native variant │
34
+ * ├──────────────────┼───────────────────────┼───────────────────────────────┤
35
+ * │ loadNodeCrypto │ `await import('crypto')` (Node built-in) │
36
+ * │ │ │ throws — Node crypto is not │
37
+ * │ │ │ available on Hermes/RN │
38
+ * ├──────────────────┼───────────────────────┼───────────────────────────────┤
39
+ * │ loadExpoCrypto │ throws — expo-crypto │ static `import 'expo-crypto'` │
40
+ * │ │ is not part of a │ │
41
+ * │ │ Node/Vite bundle │ │
42
+ * ├──────────────────┼───────────────────────┼───────────────────────────────┤
43
+ * │ loadSecureStore │ throws (web/Node have │ static `import 'expo-secure-` │
44
+ * │ │ their own storage) │ store' │
45
+ * ├──────────────────┼───────────────────────┼───────────────────────────────┤
46
+ * │ loadAsyncStorage │ throws (web/Node have │ static `import '@react- │
47
+ * │ │ their own storage) │ native-async-storage/...' │
48
+ * ├──────────────────┼───────────────────────┼───────────────────────────────┤
49
+ * │ getRandomBytesRN │ throws (RN-only) │ direct call into expo-crypto │
50
+ * └──────────────────┴───────────────────────┴───────────────────────────────┘
51
+ *
52
+ * Crucially, the default variant references ONLY Node's `'crypto'`. It never
53
+ * mentions `expo-*` or `@react-native-async-storage/*` — so Vite, webpack,
54
+ * esbuild, Rollup, and Node itself can bundle / require it without ever
55
+ * attempting to resolve those RN-only packages.
56
+ *
57
+ * The React Native variant references ONLY the RN packages. It never
58
+ * mentions `'crypto'` — so Metro and Hermes have nothing to choke on.
59
+ *
60
+ * # Why not a single file with dynamic import?
61
+ *
62
+ * A previous iteration used a "bundler-opaque" `new Function('s', 'return
63
+ * import(s)')` trick so a single file could service every platform. It
64
+ * bundled cleanly on Metro but Hermes refused to PARSE the resulting
65
+ * `import()` expression inside a Function-constructor body
66
+ * (`SyntaxError: Invalid expression encountered` at the `(` of `import(`).
67
+ * The platform-extension split is the only approach that lets each runtime
68
+ * see a file containing only specifiers it can understand — no tricks, no
69
+ * runtime parsing risks.
70
+ */
71
+ export declare function loadNodeCrypto(): Promise<typeof import('crypto')>;
72
+ export declare function loadExpoCrypto(): Promise<typeof import('expo-crypto')>;
73
+ export declare function loadSecureStore(): Promise<typeof import('expo-secure-store')>;
74
+ export declare function loadAsyncStorage(): Promise<{
75
+ default: {
76
+ getItem: (key: string) => Promise<string | null>;
77
+ setItem: (key: string, value: string) => Promise<void>;
78
+ removeItem: (key: string) => Promise<void>;
79
+ };
80
+ }>;
81
+ /**
82
+ * Synchronous random-bytes via `expo-crypto.getRandomBytes`. Only available
83
+ * in the React Native variant. The default variant throws because Node and
84
+ * browsers have their own native CSPRNGs (`crypto.randomBytes` and
85
+ * `crypto.getRandomValues` respectively) — callers should use those.
86
+ */
87
+ export declare function getRandomBytesRN(_byteCount: number): Uint8Array;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Platform Crypto / Storage — React Native Variant
3
+ *
4
+ * Companion to `./platformCrypto.ts`. See the doc-comment at the top of that
5
+ * file for the full design.
6
+ *
7
+ * Metro auto-selects this file in any non-web build (`preferNativePlatform`
8
+ * is `true` for iOS / Android, so `*.native.js` shadows `*.js` during
9
+ * source-extension resolution inside `node_modules/@oxyhq/core/dist/`). On
10
+ * iOS / Android `<base>.ios.js` / `<base>.android.js` would shadow this file
11
+ * if they existed, but they don't — `.native.js` is the shared RN variant.
12
+ *
13
+ * - The default variant references Node's `'crypto'` and would crash Metro
14
+ * if bundled into an RN app.
15
+ * - This variant references the RN-only modules (`expo-crypto`,
16
+ * `expo-secure-store`, `@react-native-async-storage/async-storage`)
17
+ * as static imports, so Metro and Hermes both resolve and parse them
18
+ * cleanly.
19
+ *
20
+ * Both variants expose the same surface; importers don't care which one
21
+ * they got.
22
+ *
23
+ * # Why static imports?
24
+ *
25
+ * Every RN consumer of `@oxyhq/core` already lists or transitively pulls
26
+ * in `expo-crypto`, `expo-secure-store`, and
27
+ * `@react-native-async-storage/async-storage` (they're stable Expo modules
28
+ * present in `services`, `accounts`, `inbox`, and `test-app`). A static
29
+ * import is what Metro wants to see anyway, and Hermes parses it like any
30
+ * other ES module — no `Function`-constructor parser exotic-mode involved.
31
+ *
32
+ * This is also clearer to debug: Metro fails up-front with a normal
33
+ * unresolved-module error if a consumer is missing a peer dep, instead of
34
+ * a confusing runtime throw the first time a code path that needs the
35
+ * module is exercised.
36
+ */
37
+ export declare function loadNodeCrypto(): Promise<typeof import('crypto')>;
38
+ export declare function loadExpoCrypto(): Promise<typeof import('expo-crypto')>;
39
+ export declare function loadSecureStore(): Promise<typeof import('expo-secure-store')>;
40
+ type AsyncStorageLike = {
41
+ getItem: (key: string) => Promise<string | null>;
42
+ setItem: (key: string, value: string) => Promise<void>;
43
+ removeItem: (key: string) => Promise<void>;
44
+ };
45
+ export declare function loadAsyncStorage(): Promise<{
46
+ default: AsyncStorageLike;
47
+ }>;
48
+ /**
49
+ * Synchronous random-bytes via `expo-crypto.getRandomBytes`. Available
50
+ * synchronously because `expo-crypto` is statically imported by this file
51
+ * — no async initialization race.
52
+ */
53
+ export declare function getRandomBytesRN(byteCount: number): Uint8Array;
54
+ export {};