@oxy.so/core 4.5.0-oxy-one.0 → 4.5.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 (285) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/HttpService.js +63 -19
  3. package/dist/cjs/api/accounts.js +10 -3
  4. package/dist/cjs/api/agency.js +3 -1
  5. package/dist/cjs/api/apps.js +15 -4
  6. package/dist/cjs/api/assets.js +49 -12
  7. package/dist/cjs/api/auth.js +37 -11
  8. package/dist/cjs/api/billing.js +24 -7
  9. package/dist/cjs/api/civic.js +14 -4
  10. package/dist/cjs/api/follows.js +9 -2
  11. package/dist/cjs/api/identity.js +31 -9
  12. package/dist/cjs/api/nodes.js +3 -1
  13. package/dist/cjs/api/privacy.js +8 -2
  14. package/dist/cjs/api/session.js +15 -4
  15. package/dist/cjs/api/store.js +15 -5
  16. package/dist/cjs/api/topics.js +10 -3
  17. package/dist/cjs/api/users.js +16 -4
  18. package/dist/cjs/boot/sessionColdBoot.js +40 -13
  19. package/dist/cjs/constants/version.js +6 -6
  20. package/dist/cjs/crypto/identityMarker.js +3 -1
  21. package/dist/cjs/crypto/identityProof.js +6 -1
  22. package/dist/cjs/crypto/keyManager.js +87 -32
  23. package/dist/cjs/crypto/recoveryPhrase.js +2 -2
  24. package/dist/cjs/crypto/signatureService.js +3 -4
  25. package/dist/cjs/i18n/index.js +16 -3
  26. package/dist/cjs/i18n/locales/ar-SA.js +366 -366
  27. package/dist/cjs/i18n/locales/ca-ES.js +366 -366
  28. package/dist/cjs/i18n/locales/de-DE.js +366 -366
  29. package/dist/cjs/i18n/locales/en-US.js +1994 -1994
  30. package/dist/cjs/i18n/locales/es-ES.js +1994 -1994
  31. package/dist/cjs/i18n/locales/fr-FR.js +366 -366
  32. package/dist/cjs/i18n/locales/it-IT.js +366 -366
  33. package/dist/cjs/i18n/locales/ja-JP.js +366 -366
  34. package/dist/cjs/i18n/locales/ko-KR.js +366 -366
  35. package/dist/cjs/i18n/locales/pt-PT.js +366 -366
  36. package/dist/cjs/i18n/locales/zh-CN.js +366 -366
  37. package/dist/cjs/inference/OxyInferenceClient.js +12 -18
  38. package/dist/cjs/models/interfaces.js +11 -11
  39. package/dist/cjs/server/OxyServer.js +86 -28
  40. package/dist/cjs/server/agentAccount.js +6 -2
  41. package/dist/cjs/server/aliaMachineCredential.js +39 -14
  42. package/dist/cjs/server/auth.js +5 -4
  43. package/dist/cjs/server/capabilityTicket.js +5 -5
  44. package/dist/cjs/server/index.js +2 -1
  45. package/dist/cjs/server/liveCapabilityTicket.js +4 -1
  46. package/dist/cjs/server/middleware.js +61 -42
  47. package/dist/cjs/server/namespaces.js +28 -7
  48. package/dist/cjs/server/requesterAssertion.js +36 -30
  49. package/dist/cjs/server/serviceTokenLifetime.js +7 -4
  50. package/dist/cjs/server/traffic.js +53 -14
  51. package/dist/cjs/server/trafficNodeHttp.js +33 -8
  52. package/dist/cjs/server/workloadIdentity.client.js +4 -0
  53. package/dist/cjs/server/workloadIdentity.js +28 -1
  54. package/dist/cjs/session/SessionClient.js +54 -17
  55. package/dist/cjs/session/accountDelegationAccess.js +4 -6
  56. package/dist/cjs/session/accountDialogController.js +1 -1
  57. package/dist/cjs/session/authStateStore.js +18 -9
  58. package/dist/cjs/session/identityPin.js +6 -2
  59. package/dist/cjs/session/refresh.js +81 -23
  60. package/dist/cjs/session/sharedDeviceCredential.js +28 -15
  61. package/dist/cjs/shared/utils/errorUtils.js +1 -1
  62. package/dist/cjs/shared/utils/networkUtils.js +1 -1
  63. package/dist/cjs/shared/utils/themeUtils.js +1 -1
  64. package/dist/cjs/utils/accountCacheSweep.js +3 -1
  65. package/dist/cjs/utils/accountUtils.js +1 -3
  66. package/dist/cjs/utils/asyncUtils.js +1 -1
  67. package/dist/cjs/utils/authHelpers.js +2 -1
  68. package/dist/cjs/utils/avatarUtils.js +4 -2
  69. package/dist/cjs/utils/cache.js +1 -1
  70. package/dist/cjs/utils/cacheKey.js +3 -1
  71. package/dist/cjs/utils/deviceManager.js +4 -4
  72. package/dist/cjs/utils/errorUtils.js +6 -4
  73. package/dist/cjs/utils/languageUtils.js +404 -57
  74. package/dist/cjs/utils/profileLinks.js +1 -3
  75. package/dist/cjs/utils/requestUtils.js +7 -1
  76. package/dist/cjs/utils/userIdentity.js +1 -1
  77. package/dist/cjs/utils/validationUtils.js +5 -6
  78. package/dist/esm/HttpService.js +64 -20
  79. package/dist/esm/api/accounts.js +11 -4
  80. package/dist/esm/api/agency.js +3 -1
  81. package/dist/esm/api/apps.js +15 -4
  82. package/dist/esm/api/assets.js +49 -12
  83. package/dist/esm/api/auth.js +37 -11
  84. package/dist/esm/api/billing.js +25 -8
  85. package/dist/esm/api/civic.js +14 -4
  86. package/dist/esm/api/follows.js +9 -2
  87. package/dist/esm/api/identity.js +31 -9
  88. package/dist/esm/api/nodes.js +3 -1
  89. package/dist/esm/api/privacy.js +8 -2
  90. package/dist/esm/api/session.js +15 -4
  91. package/dist/esm/api/store.js +15 -5
  92. package/dist/esm/api/topics.js +10 -3
  93. package/dist/esm/api/users.js +16 -4
  94. package/dist/esm/boot/sessionColdBoot.js +41 -14
  95. package/dist/esm/constants/version.js +6 -6
  96. package/dist/esm/crypto/identityMarker.js +3 -1
  97. package/dist/esm/crypto/identityProof.js +6 -1
  98. package/dist/esm/crypto/internal.js +1 -1
  99. package/dist/esm/crypto/keyManager.js +87 -32
  100. package/dist/esm/crypto/recoveryPhrase.js +2 -2
  101. package/dist/esm/crypto/signatureService.js +3 -4
  102. package/dist/esm/i18n/index.js +16 -3
  103. package/dist/esm/i18n/locales/ar-SA.js +366 -366
  104. package/dist/esm/i18n/locales/ca-ES.js +366 -366
  105. package/dist/esm/i18n/locales/de-DE.js +366 -366
  106. package/dist/esm/i18n/locales/en-US.js +1994 -1994
  107. package/dist/esm/i18n/locales/es-ES.js +1994 -1994
  108. package/dist/esm/i18n/locales/fr-FR.js +366 -366
  109. package/dist/esm/i18n/locales/it-IT.js +366 -366
  110. package/dist/esm/i18n/locales/ja-JP.js +366 -366
  111. package/dist/esm/i18n/locales/ko-KR.js +366 -366
  112. package/dist/esm/i18n/locales/pt-PT.js +366 -366
  113. package/dist/esm/i18n/locales/zh-CN.js +366 -366
  114. package/dist/esm/index.js +1 -1
  115. package/dist/esm/inference/OxyInferenceClient.js +13 -19
  116. package/dist/esm/models/interfaces.js +11 -11
  117. package/dist/esm/server/OxyServer.js +87 -29
  118. package/dist/esm/server/agentAccount.js +6 -2
  119. package/dist/esm/server/aliaMachineCredential.js +39 -14
  120. package/dist/esm/server/auth.js +6 -5
  121. package/dist/esm/server/capabilityTicket.js +6 -6
  122. package/dist/esm/server/index.js +5 -5
  123. package/dist/esm/server/liveCapabilityTicket.js +6 -3
  124. package/dist/esm/server/middleware.js +62 -43
  125. package/dist/esm/server/namespaces.js +31 -10
  126. package/dist/esm/server/requesterAssertion.js +36 -30
  127. package/dist/esm/server/serviceTokenLifetime.js +7 -4
  128. package/dist/esm/server/traffic.js +55 -16
  129. package/dist/esm/server/trafficNodeHttp.js +34 -9
  130. package/dist/esm/server/userInvalidation.js +1 -1
  131. package/dist/esm/server/workloadIdentity.client.js +3 -0
  132. package/dist/esm/server/workloadIdentity.js +27 -1
  133. package/dist/esm/session/SessionClient.js +54 -17
  134. package/dist/esm/session/accountDelegationAccess.js +5 -7
  135. package/dist/esm/session/accountDialogController.js +1 -1
  136. package/dist/esm/session/authStateStore.js +18 -9
  137. package/dist/esm/session/identityPin.js +6 -2
  138. package/dist/esm/session/refresh.js +82 -24
  139. package/dist/esm/session/sharedDeviceCredential.js +28 -15
  140. package/dist/esm/shared/utils/errorUtils.js +1 -1
  141. package/dist/esm/shared/utils/networkUtils.js +1 -1
  142. package/dist/esm/shared/utils/themeUtils.js +1 -1
  143. package/dist/esm/utils/accountCacheSweep.js +3 -1
  144. package/dist/esm/utils/accountUtils.js +1 -3
  145. package/dist/esm/utils/asyncUtils.js +1 -1
  146. package/dist/esm/utils/authHelpers.js +2 -1
  147. package/dist/esm/utils/avatarUtils.js +4 -2
  148. package/dist/esm/utils/cache.js +1 -1
  149. package/dist/esm/utils/cacheKey.js +3 -1
  150. package/dist/esm/utils/deviceManager.js +4 -4
  151. package/dist/esm/utils/errorUtils.js +6 -4
  152. package/dist/esm/utils/languageUtils.js +404 -57
  153. package/dist/esm/utils/profileLinks.js +1 -3
  154. package/dist/esm/utils/requestUtils.js +7 -1
  155. package/dist/esm/utils/userIdentity.js +1 -1
  156. package/dist/esm/utils/validationUtils.js +5 -6
  157. package/dist/types/HttpService.d.ts +1 -1
  158. package/dist/types/api/accounts.d.ts +1 -1
  159. package/dist/types/api/apps.d.ts +4 -4
  160. package/dist/types/api/assets.d.ts +2 -0
  161. package/dist/types/api/auth.d.ts +8 -3
  162. package/dist/types/crypto/internal.d.ts +1 -1
  163. package/dist/types/index.d.ts +4 -4
  164. package/dist/types/server/index.d.ts +6 -6
  165. package/dist/types/server/requesterAssertion.d.ts +2 -2
  166. package/dist/types/server/workloadIdentity.client.d.ts +5 -1
  167. package/dist/types/server/workloadIdentity.d.ts +26 -0
  168. package/dist/types/session/accountDelegationAccess.d.ts +1 -1
  169. package/dist/types/session/index.d.ts +1 -1
  170. package/dist/types/utils/userIdentity.d.ts +1 -1
  171. package/dist/types/utils/validationUtils.d.ts +4 -5
  172. package/package.json +2 -3
  173. package/src/HttpService.ts +183 -53
  174. package/src/OxyServices.errors.ts +7 -3
  175. package/src/OxyServices.ts +6 -2
  176. package/src/api/accounts.ts +76 -26
  177. package/src/api/agency.ts +24 -9
  178. package/src/api/appData.ts +12 -2
  179. package/src/api/apps.ts +81 -31
  180. package/src/api/assets.ts +122 -40
  181. package/src/api/auth.ts +154 -79
  182. package/src/api/billing.ts +112 -65
  183. package/src/api/civic.ts +61 -19
  184. package/src/api/contacts.ts +4 -1
  185. package/src/api/devices.ts +54 -21
  186. package/src/api/follows.ts +88 -31
  187. package/src/api/identity.ts +101 -33
  188. package/src/api/linkedAccounts.ts +26 -8
  189. package/src/api/nodes.ts +18 -6
  190. package/src/api/notifications.ts +26 -6
  191. package/src/api/privacy.ts +42 -8
  192. package/src/api/reputation.ts +18 -7
  193. package/src/api/session.ts +23 -5
  194. package/src/api/store.ts +81 -31
  195. package/src/api/topics.ts +18 -6
  196. package/src/api/users.ts +98 -35
  197. package/src/boot/sessionColdBoot.ts +60 -19
  198. package/src/civic/payloads.ts +1 -4
  199. package/src/client/context.ts +6 -1
  200. package/src/constants/version.ts +7 -6
  201. package/src/crypto/aead.ts +1 -5
  202. package/src/crypto/ecdh.ts +1 -4
  203. package/src/crypto/identityDerivations.ts +5 -1
  204. package/src/crypto/identityMarker.ts +3 -1
  205. package/src/crypto/identityProof.ts +6 -1
  206. package/src/crypto/index.ts +11 -11
  207. package/src/crypto/internal.ts +6 -1
  208. package/src/crypto/keyManager.ts +348 -98
  209. package/src/crypto/recoveryPhrase.ts +14 -9
  210. package/src/crypto/registrationPow.ts +1 -1
  211. package/src/crypto/signatureService.ts +14 -6
  212. package/src/i18n/accountCategoryLabels.ts +1 -4
  213. package/src/i18n/accountRoleLabels.ts +1 -4
  214. package/src/i18n/index.ts +25 -7
  215. package/src/i18n/locales/ar-SA.ts +375 -366
  216. package/src/i18n/locales/ca-ES.ts +382 -366
  217. package/src/i18n/locales/de-DE.ts +387 -366
  218. package/src/i18n/locales/en-US.ts +2034 -1994
  219. package/src/i18n/locales/es-ES.ts +2043 -1994
  220. package/src/i18n/locales/fr-FR.ts +387 -366
  221. package/src/i18n/locales/it-IT.ts +380 -366
  222. package/src/i18n/locales/ja-JP.ts +380 -366
  223. package/src/i18n/locales/ko-KR.ts +377 -366
  224. package/src/i18n/locales/pt-PT.ts +383 -366
  225. package/src/i18n/locales/zh-CN.ts +373 -366
  226. package/src/i18n/trustTierLabels.ts +1 -4
  227. package/src/index.ts +371 -349
  228. package/src/inference/OxyInferenceClient.ts +784 -780
  229. package/src/models/interfaces.ts +30 -27
  230. package/src/server/OxyServer.ts +227 -68
  231. package/src/server/agentAccount.ts +8 -2
  232. package/src/server/aliaMachineCredential.ts +57 -16
  233. package/src/server/auth.ts +9 -5
  234. package/src/server/capabilityTicket.ts +30 -21
  235. package/src/server/index.ts +29 -6
  236. package/src/server/liveCapabilityTicket.ts +31 -9
  237. package/src/server/middleware.ts +212 -121
  238. package/src/server/namespaces.ts +247 -94
  239. package/src/server/rateLimit.ts +2 -4
  240. package/src/server/requesterAssertion.ts +93 -54
  241. package/src/server/serviceTokenLifetime.ts +9 -4
  242. package/src/server/traffic.ts +117 -23
  243. package/src/server/trafficNodeHttp.ts +61 -14
  244. package/src/server/userInvalidation.ts +1 -4
  245. package/src/server/workloadIdentity.client.ts +12 -1
  246. package/src/server/workloadIdentity.ts +52 -5
  247. package/src/session/SessionClient.ts +170 -49
  248. package/src/session/accountDelegationAccess.ts +24 -31
  249. package/src/session/accountDialogController.ts +59 -14
  250. package/src/session/accountSwitchTargets.ts +10 -15
  251. package/src/session/authStateStore.ts +121 -81
  252. package/src/session/deviceDirectory.ts +1 -3
  253. package/src/session/identityPin.ts +10 -11
  254. package/src/session/identitySession.ts +3 -1
  255. package/src/session/index.ts +87 -82
  256. package/src/session/refresh.ts +138 -44
  257. package/src/session/sessionClientHost.ts +1 -3
  258. package/src/session/sharedDeviceCredential.ts +35 -14
  259. package/src/session/socketLoader.ts +9 -2
  260. package/src/shared/utils/errorUtils.ts +5 -2
  261. package/src/shared/utils/networkUtils.ts +5 -8
  262. package/src/shared/utils/themeUtils.ts +2 -6
  263. package/src/types/buffer.d.ts +66 -21
  264. package/src/types/expo-secure-store.d.ts +5 -1
  265. package/src/utils/accountCacheSweep.ts +4 -5
  266. package/src/utils/accountUtils.ts +107 -108
  267. package/src/utils/apiUtils.ts +3 -3
  268. package/src/utils/asyncUtils.ts +2 -2
  269. package/src/utils/authHelpers.ts +10 -5
  270. package/src/utils/avatarUtils.ts +11 -6
  271. package/src/utils/cache.ts +9 -10
  272. package/src/utils/cacheKey.ts +5 -1
  273. package/src/utils/coldBoot.ts +1 -3
  274. package/src/utils/commonsDelivery.ts +1 -4
  275. package/src/utils/deviceManager.ts +15 -14
  276. package/src/utils/errorUtils.ts +68 -86
  277. package/src/utils/languageUtils.ts +407 -58
  278. package/src/utils/oauthPkce.ts +1 -4
  279. package/src/utils/platform.ts +0 -1
  280. package/src/utils/profileLinks.ts +2 -5
  281. package/src/utils/requestUtils.ts +18 -14
  282. package/src/utils/sessionUtils.ts +34 -33
  283. package/src/utils/userHandle.ts +3 -1
  284. package/src/utils/userIdentity.ts +1 -1
  285. package/src/utils/validationUtils.ts +11 -9
@@ -88,7 +88,7 @@ export async function retryAsync<T>(
88
88
  operation: () => Promise<T>,
89
89
  maxRetriesOrOptions: number | RetryOptions = 3,
90
90
  baseDelayArg = 1000,
91
- shouldRetryArg?: (error: unknown) => boolean
91
+ shouldRetryArg?: (error: unknown) => boolean,
92
92
  ): Promise<T> {
93
93
  // An options-object overload rather than a fifth positional parameter:
94
94
  // `retryOnError` below and other in-tree callers pass positionally, and a
@@ -163,7 +163,7 @@ export async function retryAsync<T>(
163
163
  break;
164
164
  }
165
165
 
166
- await new Promise(resolve => setTimeout(resolve, delay));
166
+ await new Promise((resolve) => setTimeout(resolve, delay));
167
167
  }
168
168
  }
169
169
 
@@ -36,7 +36,7 @@ export class AuthenticationFailedError extends Error {
36
36
  export async function ensureValidToken(
37
37
  oxyServices: OxyServices,
38
38
  _activeSessionId: string | null | undefined,
39
- syncSession?: () => Promise<unknown>
39
+ syncSession?: () => Promise<unknown>,
40
40
  ): Promise<void> {
41
41
  if (oxyServices.session.isAuthenticated) {
42
42
  return;
@@ -51,7 +51,10 @@ export async function ensureValidToken(
51
51
  } catch (syncError) {
52
52
  const errorMessage = syncError instanceof Error ? syncError.message : String(syncError);
53
53
 
54
- if (errorMessage.includes('AUTH_REQUIRED_OFFLINE_SESSION') || errorMessage.includes('offline')) {
54
+ if (
55
+ errorMessage.includes('AUTH_REQUIRED_OFFLINE_SESSION') ||
56
+ errorMessage.includes('offline')
57
+ ) {
55
58
  throw new SessionSyncRequiredError();
56
59
  }
57
60
 
@@ -59,7 +62,9 @@ export async function ensureValidToken(
59
62
  }
60
63
  }
61
64
 
62
- throw new SessionSyncRequiredError('No active access token is available. Sync the session before calling authenticated APIs.');
65
+ throw new SessionSyncRequiredError(
66
+ 'No active access token is available. Sync the session before calling authenticated APIs.',
67
+ );
63
68
  }
64
69
 
65
70
  /**
@@ -98,7 +103,7 @@ export function isAuthenticationError(error: unknown): boolean {
98
103
  */
99
104
  export async function withAuthErrorHandling<T>(
100
105
  apiCall: () => Promise<T>,
101
- options?: HandleApiErrorOptions
106
+ options?: HandleApiErrorOptions,
102
107
  ): Promise<T> {
103
108
  try {
104
109
  return await apiCall();
@@ -136,7 +141,7 @@ export async function authenticatedApiCall<T>(
136
141
  oxyServices: OxyServices,
137
142
  activeSessionId: string | null | undefined,
138
143
  apiCall: () => Promise<T>,
139
- syncSession?: () => Promise<unknown>
144
+ syncSession?: () => Promise<unknown>,
140
145
  ): Promise<T> {
141
146
  await ensureValidToken(oxyServices, activeSessionId, syncSession);
142
147
 
@@ -2,7 +2,9 @@ import { logger } from '../logger';
2
2
 
3
3
  /** What `updateAvatarVisibility` needs of a client: `oxy.assets.setVisibility`. */
4
4
  export interface AssetVisibilityService {
5
- assets: { setVisibility(fileId: string, visibility: 'private' | 'public' | 'unlisted'): Promise<unknown> };
5
+ assets: {
6
+ setVisibility(fileId: string, visibility: 'private' | 'public' | 'unlisted'): Promise<unknown>;
7
+ };
6
8
  }
7
9
 
8
10
  /**
@@ -16,7 +18,7 @@ export interface AssetVisibilityService {
16
18
  export async function updateAvatarVisibility(
17
19
  fileId: string | undefined,
18
20
  oxyServices: AssetVisibilityService,
19
- contextName = 'AvatarUtils'
21
+ contextName = 'AvatarUtils',
20
22
  ): Promise<void> {
21
23
  if (!fileId || fileId.startsWith('temp-')) {
22
24
  return;
@@ -26,11 +28,14 @@ export async function updateAvatarVisibility(
26
28
  await oxyServices.assets.setVisibility(fileId, 'public');
27
29
  } catch (visError: unknown) {
28
30
  // 404 is expected when asset doesn't exist yet — skip logging
29
- const status = (visError instanceof Error && 'status' in visError)
30
- ? (visError as Error & { status: number }).status
31
- : undefined;
31
+ const status =
32
+ visError instanceof Error && 'status' in visError
33
+ ? (visError as Error & { status: number }).status
34
+ : undefined;
32
35
  if (status !== 404) {
33
- logger.error(`[${contextName}] Failed to update avatar visibility for ${fileId}`, visError, { component: contextName });
36
+ logger.error(`[${contextName}] Failed to update avatar visibility for ${fileId}`, visError, {
37
+ component: contextName,
38
+ });
34
39
  }
35
40
  }
36
41
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Centralized cache utility with TTL support
3
- *
3
+ *
4
4
  * This is a production-ready cache implementation used across the codebase
5
5
  * for consistent caching behavior and performance optimization.
6
6
  */
@@ -26,26 +26,26 @@ export interface CacheStats {
26
26
 
27
27
  /**
28
28
  * TTL-based cache implementation
29
- *
29
+ *
30
30
  * Features:
31
31
  * - Automatic expiration based on TTL
32
32
  * - Manual cleanup of expired entries
33
33
  * - Statistics tracking (hits, misses, hit rate)
34
34
  * - Type-safe generic interface
35
- *
35
+ *
36
36
  * @example
37
37
  * ```typescript
38
38
  * const cache = new TTLCache<string>(5 * 60 * 1000); // 5 minutes
39
- *
39
+ *
40
40
  * // Set with default TTL
41
41
  * cache.set('key', 'value');
42
- *
42
+ *
43
43
  * // Set with custom TTL
44
44
  * cache.set('key', 'value', 10 * 60 * 1000); // 10 minutes
45
- *
45
+ *
46
46
  * // Get value
47
47
  * const value = cache.get('key');
48
- *
48
+ *
49
49
  * // Get statistics
50
50
  * const stats = cache.getStats();
51
51
  * ```
@@ -244,7 +244,7 @@ export class TTLCache<T> {
244
244
 
245
245
  /**
246
246
  * Create a TTL cache instance (convenience function)
247
- *
247
+ *
248
248
  * @example
249
249
  * ```typescript
250
250
  * const cache = createCache<string>(5 * 60 * 1000);
@@ -272,7 +272,7 @@ export function registerCacheForCleanup(cache: TTLCache<unknown>): void {
272
272
 
273
273
  /** Empty registered caches need no timer; importing a client must stay inert. */
274
274
  function updateCleanupInterval(): void {
275
- const hasEntries = [...activeCaches].some(cache => cache.size() > 0);
275
+ const hasEntries = [...activeCaches].some((cache) => cache.size() > 0);
276
276
  if (!hasEntries) {
277
277
  if (cleanupInterval) clearInterval(cleanupInterval);
278
278
  cleanupInterval = null;
@@ -303,4 +303,3 @@ export function stopAllCleanupIntervals(): void {
303
303
  }
304
304
  activeCaches.clear();
305
305
  }
306
-
@@ -85,5 +85,9 @@ export function computeIdentityTag(accessToken: string | null): string {
85
85
  const decoded = decodeTokenClaims(accessToken);
86
86
  // An undecodable token is still partitioned away from anon and from other
87
87
  // tokens via a hash — never silently ANON_IDENTITY.
88
- return (decoded?.userId as string | undefined) || (decoded?.id as string | undefined) || `t${fnv1a32(accessToken)}`;
88
+ return (
89
+ (decoded?.userId as string | undefined) ||
90
+ (decoded?.id as string | undefined) ||
91
+ `t${fnv1a32(accessToken)}`
92
+ );
89
93
  }
@@ -141,9 +141,7 @@ export interface RunColdBootOptions<S> {
141
141
  * - `{ kind: 'skip' }` → continue.
142
142
  * 4. After the loop with no winner → `{ kind: 'unauthenticated' }`.
143
143
  */
144
- export async function runColdBoot<S>(
145
- options: RunColdBootOptions<S>
146
- ): Promise<ColdBootOutcome<S>> {
144
+ export async function runColdBoot<S>(options: RunColdBootOptions<S>): Promise<ColdBootOutcome<S>> {
147
145
  const { steps, onStepError, overallDeadlineMs, onStepDeadline } = options;
148
146
 
149
147
  // Arm the optional overall deadline. The budget is SHARED across the whole
@@ -108,10 +108,7 @@ export function selectCommonsDelivery(facts: CommonsDeliveryFacts): CommonsDeliv
108
108
  * `delivered: false` with `targets > 0`, which must NOT park the user on
109
109
  * "check your phone".
110
110
  */
111
- export function pushTargetsFromDelivery(result: {
112
- delivered: boolean;
113
- targets: number;
114
- }): number {
111
+ export function pushTargetsFromDelivery(result: { delivered: boolean; targets: number }): number {
115
112
  return result.delivered ? result.targets : 0;
116
113
  }
117
114
 
@@ -30,14 +30,14 @@ export interface StoredDeviceInfo {
30
30
  // biome-ignore lint/complexity/noStaticOnlyClass: a public, static-only API surface (`X.method()`) that consumers and tests call and spy on by name.
31
31
  export class DeviceManager {
32
32
  private static DEVICE_KEY = 'oxy_device_info';
33
-
33
+
34
34
  /**
35
35
  * Check if we're in React Native environment
36
36
  */
37
37
  private static isReactNative(): boolean {
38
38
  return typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
39
39
  }
40
-
40
+
41
41
  /**
42
42
  * Get appropriate storage for the platform
43
43
  */
@@ -67,11 +67,11 @@ export class DeviceManager {
67
67
  return {
68
68
  getItem: async (key: string) => localStorage.getItem(key),
69
69
  setItem: async (key: string, value: string) => localStorage.setItem(key, value),
70
- removeItem: async (key: string) => localStorage.removeItem(key)
70
+ removeItem: async (key: string) => localStorage.removeItem(key),
71
71
  };
72
72
  }
73
73
  }
74
-
74
+
75
75
  /**
76
76
  * Get or create device fingerprint for current device
77
77
  */
@@ -80,7 +80,8 @@ export class DeviceManager {
80
80
  userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'unknown',
81
81
  platform: typeof navigator !== 'undefined' ? navigator.platform : 'unknown',
82
82
  language: typeof navigator !== 'undefined' ? navigator.language : undefined,
83
- timezone: typeof Intl !== 'undefined' ? Intl.DateTimeFormat().resolvedOptions().timeZone : undefined,
83
+ timezone:
84
+ typeof Intl !== 'undefined' ? Intl.DateTimeFormat().resolvedOptions().timeZone : undefined,
84
85
  };
85
86
 
86
87
  // Add screen info if available
@@ -88,7 +89,7 @@ export class DeviceManager {
88
89
  fingerprint.screen = {
89
90
  width: screen.width,
90
91
  height: screen.height,
91
- colorDepth: screen.colorDepth
92
+ colorDepth: screen.colorDepth,
92
93
  };
93
94
  }
94
95
 
@@ -102,17 +103,17 @@ export class DeviceManager {
102
103
  try {
103
104
  const storage = await DeviceManager.getStorage();
104
105
  const stored = await storage.getItem(DeviceManager.DEVICE_KEY);
105
-
106
+
106
107
  if (stored) {
107
108
  const deviceInfo: StoredDeviceInfo = JSON.parse(stored);
108
-
109
+
109
110
  // Update last used timestamp
110
111
  deviceInfo.lastUsed = new Date().toISOString();
111
112
  await DeviceManager.saveDeviceInfo(deviceInfo);
112
-
113
+
113
114
  return deviceInfo;
114
115
  }
115
-
116
+
116
117
  // Create new device info
117
118
  return await DeviceManager.createNewDeviceInfo();
118
119
  } catch (error) {
@@ -129,7 +130,7 @@ export class DeviceManager {
129
130
  deviceId: DeviceManager.generateDeviceId(),
130
131
  fingerprint: JSON.stringify(DeviceManager.getDeviceFingerprint()),
131
132
  createdAt: new Date().toISOString(),
132
- lastUsed: new Date().toISOString()
133
+ lastUsed: new Date().toISOString(),
133
134
  };
134
135
 
135
136
  await DeviceManager.saveDeviceInfo(deviceInfo);
@@ -180,7 +181,7 @@ export class DeviceManager {
180
181
  if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
181
182
  const array = new Uint8Array(32);
182
183
  crypto.getRandomValues(array);
183
- return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
184
+ return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join('');
184
185
  }
185
186
  throw new Error('No secure random source available for device ID generation');
186
187
  }
@@ -191,14 +192,14 @@ export class DeviceManager {
191
192
  static getDefaultDeviceName(): string {
192
193
  const fingerprint = DeviceManager.getDeviceFingerprint();
193
194
  const platform = (fingerprint.platform || '').toLowerCase();
194
-
195
+
195
196
  if (platform.includes('win')) return 'Windows Computer';
196
197
  if (platform.includes('mac')) return 'Mac Computer';
197
198
  if (platform.includes('linux')) return 'Linux Computer';
198
199
  if (platform.includes('iphone')) return 'iPhone';
199
200
  if (platform.includes('ipad')) return 'iPad';
200
201
  if (platform.includes('android')) return 'Android Device';
201
-
202
+
202
203
  return 'Unknown Device';
203
204
  }
204
205
  }
@@ -14,23 +14,23 @@ export const ErrorCodes = {
14
14
  FORBIDDEN: 'FORBIDDEN',
15
15
  INVALID_TOKEN: 'INVALID_TOKEN',
16
16
  MISSING_TOKEN: 'MISSING_TOKEN',
17
-
17
+
18
18
  // Validation errors
19
19
  VALIDATION_ERROR: 'VALIDATION_ERROR',
20
20
  BAD_REQUEST: 'BAD_REQUEST',
21
21
  MISSING_PARAMETER: 'MISSING_PARAMETER',
22
22
  INVALID_FORMAT: 'INVALID_FORMAT',
23
-
23
+
24
24
  // Resource errors
25
25
  NOT_FOUND: 'NOT_FOUND',
26
26
  ALREADY_EXISTS: 'ALREADY_EXISTS',
27
27
  CONFLICT: 'CONFLICT',
28
-
28
+
29
29
  // Server errors
30
30
  INTERNAL_ERROR: 'INTERNAL_ERROR',
31
31
  SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE',
32
32
  TIMEOUT: 'TIMEOUT',
33
-
33
+
34
34
  // Network errors
35
35
  NETWORK_ERROR: 'NETWORK_ERROR',
36
36
  CONNECTION_FAILED: 'CONNECTION_FAILED',
@@ -47,7 +47,7 @@ export const ErrorCodes = {
47
47
  * nothing may retry it. See `retryAsync`'s default predicate, which refuses
48
48
  * this code specifically.
49
49
  */
50
- CANCELLED: 'CANCELLED'
50
+ CANCELLED: 'CANCELLED',
51
51
  } as const;
52
52
 
53
53
  /**
@@ -61,22 +61,22 @@ export const ErrorCodes = {
61
61
  * Narrow a caught value with {@link isHttpRequestError} instead of asserting.
62
62
  */
63
63
  export interface HttpRequestError extends Error {
64
- /** HTTP status of the failed response. */
64
+ /** HTTP status of the failed response. */
65
+ status: number;
66
+ /** Machine-readable code the server sent, when it sent one. */
67
+ code?: string;
68
+ /** Structured error detail the server sent, when it sent an object. */
69
+ details?: Record<string, unknown>;
70
+ /**
71
+ * Present on errors thrown directly by `HttpService`. `data` is the parsed
72
+ * JSON error body verbatim — the escape hatch for any server field the SDK
73
+ * does not lift onto `code`/`details`.
74
+ */
75
+ response?: {
65
76
  status: number;
66
- /** Machine-readable code the server sent, when it sent one. */
67
- code?: string;
68
- /** Structured error detail the server sent, when it sent an object. */
69
- details?: Record<string, unknown>;
70
- /**
71
- * Present on errors thrown directly by `HttpService`. `data` is the parsed
72
- * JSON error body verbatim — the escape hatch for any server field the SDK
73
- * does not lift onto `code`/`details`.
74
- */
75
- response?: {
76
- status: number;
77
- statusText: string;
78
- data?: unknown;
79
- };
77
+ statusText: string;
78
+ data?: unknown;
79
+ };
80
80
  }
81
81
 
82
82
  /**
@@ -87,26 +87,26 @@ export interface HttpRequestError extends Error {
87
87
  * first if you need one normalized.
88
88
  */
89
89
  export function isHttpRequestError(value: unknown): value is HttpRequestError {
90
- if (!(value instanceof Error)) {
91
- return false;
92
- }
93
- return typeof (value as Partial<HttpRequestError>).status === 'number';
90
+ if (!(value instanceof Error)) {
91
+ return false;
92
+ }
93
+ return typeof (value as Partial<HttpRequestError>).status === 'number';
94
94
  }
95
95
 
96
96
  /**
97
97
  * The fields {@link parseHttpErrorBody} lifts off a parsed error response body.
98
98
  */
99
99
  export interface ParsedHttpErrorBody {
100
- message?: string;
101
- code?: string;
102
- details?: Record<string, unknown>;
100
+ message?: string;
101
+ code?: string;
102
+ details?: Record<string, unknown>;
103
103
  }
104
104
 
105
105
  const isPlainRecord = (value: unknown): value is Record<string, unknown> =>
106
- typeof value === 'object' && value !== null && !Array.isArray(value);
106
+ typeof value === 'object' && value !== null && !Array.isArray(value);
107
107
 
108
108
  const nonEmptyString = (value: unknown): string | undefined =>
109
- typeof value === 'string' && value.trim().length > 0 ? value : undefined;
109
+ typeof value === 'string' && value.trim().length > 0 ? value : undefined;
110
110
 
111
111
  /**
112
112
  * Extract `message` / `code` / `details` from a parsed HTTP error response body.
@@ -131,27 +131,27 @@ const nonEmptyString = (value: unknown): string | undefined =>
131
131
  * its status-based fallback message. Total function: never throws.
132
132
  */
133
133
  export function parseHttpErrorBody(body: unknown): ParsedHttpErrorBody {
134
- if (!isPlainRecord(body)) {
135
- return {};
136
- }
134
+ if (!isPlainRecord(body)) {
135
+ return {};
136
+ }
137
137
 
138
- const nested = isPlainRecord(body.error) ? body.error : undefined;
139
- const errorString = nonEmptyString(body.error);
140
- // A sibling that proves the top-level `error` is a CODE rather than prose.
141
- const siblingMessage = nonEmptyString(body.message) ?? nonEmptyString(body.error_description);
142
-
143
- return {
144
- message: siblingMessage ?? (nested ? nonEmptyString(nested.message) : errorString),
145
- code:
146
- (nested ? nonEmptyString(nested.code) : undefined) ??
147
- nonEmptyString(body.code) ??
148
- (siblingMessage ? errorString : undefined),
149
- details: isPlainRecord(body.details)
150
- ? body.details
151
- : nested && isPlainRecord(nested.details)
152
- ? nested.details
153
- : undefined,
154
- };
138
+ const nested = isPlainRecord(body.error) ? body.error : undefined;
139
+ const errorString = nonEmptyString(body.error);
140
+ // A sibling that proves the top-level `error` is a CODE rather than prose.
141
+ const siblingMessage = nonEmptyString(body.message) ?? nonEmptyString(body.error_description);
142
+
143
+ return {
144
+ message: siblingMessage ?? (nested ? nonEmptyString(nested.message) : errorString),
145
+ code:
146
+ (nested ? nonEmptyString(nested.code) : undefined) ??
147
+ nonEmptyString(body.code) ??
148
+ (siblingMessage ? errorString : undefined),
149
+ details: isPlainRecord(body.details)
150
+ ? body.details
151
+ : nested && isPlainRecord(nested.details)
152
+ ? nested.details
153
+ : undefined,
154
+ };
155
155
  }
156
156
 
157
157
  /**
@@ -161,13 +161,13 @@ export function createApiError(
161
161
  message: string,
162
162
  code: string = ErrorCodes.INTERNAL_ERROR,
163
163
  status = 500,
164
- details?: Record<string, unknown>
164
+ details?: Record<string, unknown>,
165
165
  ): ApiError {
166
166
  return {
167
167
  message,
168
168
  code,
169
169
  status,
170
- details
170
+ details,
171
171
  };
172
172
  }
173
173
 
@@ -251,28 +251,24 @@ export function handleHttpError(error: unknown): ApiError {
251
251
  // anywhere else, and it stays TIMEOUT: a caller that never passed a signal
252
252
  // cannot have cancelled anything.
253
253
  if (isAbortLike(error)) {
254
- return createApiError(
255
- 'Request timeout or cancelled',
256
- ErrorCodes.TIMEOUT,
257
- 0
258
- );
254
+ return createApiError('Request timeout or cancelled', ErrorCodes.TIMEOUT, 0);
259
255
  }
260
256
 
261
257
  // Handle TypeError (network failures, CORS, etc.)
262
258
  if (error instanceof TypeError) {
263
259
  // Check if it's a network-related TypeError
264
- if (error.message.includes('fetch') || error.message.includes('network') || error.message.includes('Failed to fetch')) {
260
+ if (
261
+ error.message.includes('fetch') ||
262
+ error.message.includes('network') ||
263
+ error.message.includes('Failed to fetch')
264
+ ) {
265
265
  return createApiError(
266
266
  'Network error - failed to connect to server',
267
267
  ErrorCodes.NETWORK_ERROR,
268
- 0
268
+ 0,
269
269
  );
270
270
  }
271
- return createApiError(
272
- error.message || 'Network error occurred',
273
- ErrorCodes.NETWORK_ERROR,
274
- 0
275
- );
271
+ return createApiError(error.message || 'Network error occurred', ErrorCodes.NETWORK_ERROR, 0);
276
272
  }
277
273
 
278
274
  // Handle fetch Response errors - check if it has response property with status
@@ -298,7 +294,7 @@ export function handleHttpError(error: unknown): ApiError {
298
294
  fetchError.message || `HTTP ${status} error`,
299
295
  getErrorCodeFromStatus(status),
300
296
  status,
301
- isPlainRecord(fetchError.details) ? fetchError.details : undefined
297
+ isPlainRecord(fetchError.details) ? fetchError.details : undefined,
302
298
  );
303
299
  }
304
300
  }
@@ -307,36 +303,24 @@ export function handleHttpError(error: unknown): ApiError {
307
303
  if (error instanceof Error) {
308
304
  // Check for common error patterns
309
305
  if (error.message.includes('timeout') || error.message.includes('aborted')) {
310
- return createApiError(
311
- 'Request timeout',
312
- ErrorCodes.TIMEOUT,
313
- 0
314
- );
306
+ return createApiError('Request timeout', ErrorCodes.TIMEOUT, 0);
315
307
  }
316
-
308
+
317
309
  if (error.message.includes('network') || error.message.includes('fetch')) {
318
- return createApiError(
319
- error.message || 'Network error occurred',
320
- ErrorCodes.NETWORK_ERROR,
321
- 0
322
- );
310
+ return createApiError(error.message || 'Network error occurred', ErrorCodes.NETWORK_ERROR, 0);
323
311
  }
324
312
 
325
313
  return createApiError(
326
314
  error.message || 'Unknown error occurred',
327
315
  ErrorCodes.INTERNAL_ERROR,
328
- 500
316
+ 500,
329
317
  );
330
318
  }
331
319
 
332
320
  // Handle other errors - ensure we always return a non-empty message
333
321
  const errorString = error ? String(error) : '';
334
322
  const message = errorString.trim() || 'Unknown error occurred';
335
- return createApiError(
336
- message,
337
- ErrorCodes.INTERNAL_ERROR,
338
- 500
339
- );
323
+ return createApiError(message, ErrorCodes.INTERNAL_ERROR, 500);
340
324
  }
341
325
 
342
326
  /**
@@ -395,13 +379,13 @@ export function extractErrorStatus(error: unknown): number | undefined {
395
379
  * Validate required fields and throw error if missing
396
380
  */
397
381
  export function validateRequiredFields(data: Record<string, unknown>, fields: string[]): void {
398
- const missing = fields.filter(field => !data[field]);
399
-
382
+ const missing = fields.filter((field) => !data[field]);
383
+
400
384
  if (missing.length > 0) {
401
385
  throw createApiError(
402
386
  `Missing required fields: ${missing.join(', ')}`,
403
387
  ErrorCodes.MISSING_PARAMETER,
404
- 400
388
+ 400,
405
389
  );
406
390
  }
407
391
  }
@@ -423,5 +407,3 @@ export function logError(error: unknown, context?: string): void {
423
407
  });
424
408
  }
425
409
  }
426
-
427
-