@oxy.so/core 4.5.0-oxy-one.1 → 4.6.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 (283) 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 +39 -11
  7. package/dist/cjs/api/auth.js +28 -8
  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 +39 -11
  83. package/dist/esm/api/auth.js +28 -8
  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 +16 -3
  159. package/dist/types/api/apps.d.ts +4 -4
  160. package/dist/types/crypto/internal.d.ts +1 -1
  161. package/dist/types/index.d.ts +4 -4
  162. package/dist/types/models/interfaces.d.ts +9 -1
  163. package/dist/types/server/index.d.ts +6 -6
  164. package/dist/types/server/workloadIdentity.client.d.ts +5 -1
  165. package/dist/types/server/workloadIdentity.d.ts +26 -0
  166. package/dist/types/session/accountDelegationAccess.d.ts +1 -1
  167. package/dist/types/session/index.d.ts +1 -1
  168. package/dist/types/utils/userIdentity.d.ts +1 -1
  169. package/dist/types/utils/validationUtils.d.ts +4 -5
  170. package/package.json +3 -4
  171. package/src/HttpService.ts +183 -53
  172. package/src/OxyServices.errors.ts +7 -3
  173. package/src/OxyServices.ts +6 -2
  174. package/src/api/accounts.ts +96 -28
  175. package/src/api/agency.ts +24 -9
  176. package/src/api/appData.ts +12 -2
  177. package/src/api/apps.ts +81 -31
  178. package/src/api/assets.ts +113 -43
  179. package/src/api/auth.ts +145 -77
  180. package/src/api/billing.ts +112 -65
  181. package/src/api/civic.ts +61 -19
  182. package/src/api/contacts.ts +4 -1
  183. package/src/api/devices.ts +54 -21
  184. package/src/api/follows.ts +88 -31
  185. package/src/api/identity.ts +101 -33
  186. package/src/api/linkedAccounts.ts +26 -8
  187. package/src/api/nodes.ts +18 -6
  188. package/src/api/notifications.ts +26 -6
  189. package/src/api/privacy.ts +42 -8
  190. package/src/api/reputation.ts +18 -7
  191. package/src/api/session.ts +23 -5
  192. package/src/api/store.ts +81 -31
  193. package/src/api/topics.ts +18 -6
  194. package/src/api/users.ts +98 -35
  195. package/src/boot/sessionColdBoot.ts +60 -19
  196. package/src/civic/payloads.ts +1 -4
  197. package/src/client/context.ts +6 -1
  198. package/src/constants/version.ts +7 -6
  199. package/src/crypto/aead.ts +1 -5
  200. package/src/crypto/ecdh.ts +1 -4
  201. package/src/crypto/identityDerivations.ts +5 -1
  202. package/src/crypto/identityMarker.ts +3 -1
  203. package/src/crypto/identityProof.ts +6 -1
  204. package/src/crypto/index.ts +11 -11
  205. package/src/crypto/internal.ts +6 -1
  206. package/src/crypto/keyManager.ts +348 -98
  207. package/src/crypto/recoveryPhrase.ts +14 -9
  208. package/src/crypto/registrationPow.ts +1 -1
  209. package/src/crypto/signatureService.ts +14 -6
  210. package/src/i18n/accountCategoryLabels.ts +1 -4
  211. package/src/i18n/accountRoleLabels.ts +1 -4
  212. package/src/i18n/index.ts +25 -7
  213. package/src/i18n/locales/ar-SA.ts +375 -366
  214. package/src/i18n/locales/ca-ES.ts +382 -366
  215. package/src/i18n/locales/de-DE.ts +387 -366
  216. package/src/i18n/locales/en-US.ts +2034 -1994
  217. package/src/i18n/locales/es-ES.ts +2043 -1994
  218. package/src/i18n/locales/fr-FR.ts +387 -366
  219. package/src/i18n/locales/it-IT.ts +380 -366
  220. package/src/i18n/locales/ja-JP.ts +380 -366
  221. package/src/i18n/locales/ko-KR.ts +377 -366
  222. package/src/i18n/locales/pt-PT.ts +383 -366
  223. package/src/i18n/locales/zh-CN.ts +373 -366
  224. package/src/i18n/trustTierLabels.ts +1 -4
  225. package/src/index.ts +371 -349
  226. package/src/inference/OxyInferenceClient.ts +784 -780
  227. package/src/models/interfaces.ts +39 -27
  228. package/src/server/OxyServer.ts +227 -68
  229. package/src/server/agentAccount.ts +8 -2
  230. package/src/server/aliaMachineCredential.ts +57 -16
  231. package/src/server/auth.ts +9 -5
  232. package/src/server/capabilityTicket.ts +30 -21
  233. package/src/server/index.ts +29 -6
  234. package/src/server/liveCapabilityTicket.ts +31 -9
  235. package/src/server/middleware.ts +212 -121
  236. package/src/server/namespaces.ts +247 -94
  237. package/src/server/rateLimit.ts +2 -4
  238. package/src/server/requesterAssertion.ts +93 -54
  239. package/src/server/serviceTokenLifetime.ts +9 -4
  240. package/src/server/traffic.ts +117 -23
  241. package/src/server/trafficNodeHttp.ts +61 -14
  242. package/src/server/userInvalidation.ts +1 -4
  243. package/src/server/workloadIdentity.client.ts +12 -1
  244. package/src/server/workloadIdentity.ts +52 -5
  245. package/src/session/SessionClient.ts +170 -49
  246. package/src/session/accountDelegationAccess.ts +24 -31
  247. package/src/session/accountDialogController.ts +59 -14
  248. package/src/session/accountSwitchTargets.ts +10 -15
  249. package/src/session/authStateStore.ts +121 -81
  250. package/src/session/deviceDirectory.ts +1 -3
  251. package/src/session/identityPin.ts +10 -11
  252. package/src/session/identitySession.ts +3 -1
  253. package/src/session/index.ts +87 -82
  254. package/src/session/refresh.ts +138 -44
  255. package/src/session/sessionClientHost.ts +1 -3
  256. package/src/session/sharedDeviceCredential.ts +35 -14
  257. package/src/session/socketLoader.ts +9 -2
  258. package/src/shared/utils/errorUtils.ts +5 -2
  259. package/src/shared/utils/networkUtils.ts +5 -8
  260. package/src/shared/utils/themeUtils.ts +2 -6
  261. package/src/types/buffer.d.ts +66 -21
  262. package/src/types/expo-secure-store.d.ts +5 -1
  263. package/src/utils/accountCacheSweep.ts +4 -5
  264. package/src/utils/accountUtils.ts +107 -108
  265. package/src/utils/apiUtils.ts +3 -3
  266. package/src/utils/asyncUtils.ts +2 -2
  267. package/src/utils/authHelpers.ts +10 -5
  268. package/src/utils/avatarUtils.ts +11 -6
  269. package/src/utils/cache.ts +9 -10
  270. package/src/utils/cacheKey.ts +5 -1
  271. package/src/utils/coldBoot.ts +1 -3
  272. package/src/utils/commonsDelivery.ts +1 -4
  273. package/src/utils/deviceManager.ts +15 -14
  274. package/src/utils/errorUtils.ts +68 -86
  275. package/src/utils/languageUtils.ts +407 -58
  276. package/src/utils/oauthPkce.ts +1 -4
  277. package/src/utils/platform.ts +0 -1
  278. package/src/utils/profileLinks.ts +2 -5
  279. package/src/utils/requestUtils.ts +18 -14
  280. package/src/utils/sessionUtils.ts +34 -33
  281. package/src/utils/userHandle.ts +3 -1
  282. package/src/utils/userIdentity.ts +1 -1
  283. package/src/utils/validationUtils.ts +11 -9
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Unified HTTP Service
3
- *
3
+ *
4
4
  * Consolidates HttpClient + RequestManager into a single efficient class.
5
5
  * Uses native fetch instead of axios for smaller bundle size.
6
- *
6
+ *
7
7
  * Handles:
8
8
  * - Authentication (token management, auto-refresh)
9
9
  * - Caching (TTL-based)
@@ -16,7 +16,13 @@
16
16
  import { TTLCache, registerCacheForCleanup, unregisterCacheFromCleanup } from './utils/cache';
17
17
  import { RequestDeduplicator, RequestQueue, SimpleLogger } from './utils/requestUtils';
18
18
  import { retryAsync } from './utils/asyncUtils';
19
- import { createCancelledError, ErrorCodes, handleHttpError, isCancelledError, parseHttpErrorBody } from './utils/errorUtils';
19
+ import {
20
+ createCancelledError,
21
+ ErrorCodes,
22
+ handleHttpError,
23
+ isCancelledError,
24
+ parseHttpErrorBody,
25
+ } from './utils/errorUtils';
20
26
  import { decodeTokenClaims } from './utils/tokenClaims';
21
27
  import { isReactNative } from '@oxy.so/protocol/random';
22
28
  import { computeIdentityTag, fnv1a32 } from './utils/cacheKey';
@@ -46,15 +52,25 @@ function sameTokenSession(left: string | null, right: string | null): boolean {
46
52
  if (!a || !b || !(a.userId || a.id || a.sub) || !(b.userId || b.id || b.sub)) return false;
47
53
  // A refresh may rotate exp/iat/jti while preserving its account and session.
48
54
  // Opaque/malformed context fields cannot establish that equivalence.
49
- return ['userId', 'id', 'sub', 'sessionId', 'operatorId', 'clientId', 'appId', 'authMethodId'].every((key) =>
50
- (a[key] === undefined || typeof a[key] === 'string') && a[key] === b[key]);
55
+ return [
56
+ 'userId',
57
+ 'id',
58
+ 'sub',
59
+ 'sessionId',
60
+ 'operatorId',
61
+ 'clientId',
62
+ 'appId',
63
+ 'authMethodId',
64
+ ].every((key) => (a[key] === undefined || typeof a[key] === 'string') && a[key] === b[key]);
51
65
  }
52
66
 
53
67
  /** Cancel this wait only; the shared mint continues for other callers. */
54
68
  function awaitRequestSignal<T>(pending: Promise<T>, signal?: AbortSignal): Promise<T> {
55
69
  if (!signal) return pending;
56
70
  return new Promise<T>((resolve, reject) => {
57
- const onAbort = (): void => { reject(createCancelledError()); };
71
+ const onAbort = (): void => {
72
+ reject(createCancelledError());
73
+ };
58
74
  if (signal.aborted) onAbort();
59
75
  else signal.addEventListener('abort', onAbort, { once: true });
60
76
  // Both handlers remain attached even after cancellation, so a late shared
@@ -336,7 +352,9 @@ function isAbortLike(error: unknown): boolean {
336
352
  function linkAbort(parent: AbortSignal, child: AbortController): () => void {
337
353
  if (parent.aborted) {
338
354
  child.abort((parent as AbortSignal & { reason?: unknown }).reason);
339
- return () => { /* nothing was ever attached */ };
355
+ return () => {
356
+ /* nothing was ever attached */
357
+ };
340
358
  }
341
359
  const onAbort = (): void => {
342
360
  child.abort((parent as AbortSignal & { reason?: unknown }).reason);
@@ -461,11 +479,11 @@ export class HttpService {
461
479
  this.config = config;
462
480
  this.baseURL = config.baseURL;
463
481
  this.tokenStore = new TokenStore();
464
-
482
+
465
483
  this.logger = new SimpleLogger(
466
484
  config.enableLogging || false,
467
485
  config.logLevel || 'error',
468
- 'HttpService'
486
+ 'HttpService',
469
487
  );
470
488
 
471
489
  // Initialize performance infrastructure. The per-instance GET response
@@ -475,16 +493,17 @@ export class HttpService {
475
493
  // the cache for the global cleanup interval. Default (config unset) keeps
476
494
  // caching ON with the 5-minute TTL — unchanged for existing consumers.
477
495
  this.cacheDisabled =
478
- config.enableCache === false ||
479
- (typeof config.cacheTTL === 'number' && config.cacheTTL <= 0);
480
- this.cache = new TTLCache<unknown>(config.cacheTTL && config.cacheTTL > 0 ? config.cacheTTL : 5 * 60 * 1000);
496
+ config.enableCache === false || (typeof config.cacheTTL === 'number' && config.cacheTTL <= 0);
497
+ this.cache = new TTLCache<unknown>(
498
+ config.cacheTTL && config.cacheTTL > 0 ? config.cacheTTL : 5 * 60 * 1000,
499
+ );
481
500
  if (!this.cacheDisabled) {
482
501
  registerCacheForCleanup(this.cache);
483
502
  }
484
503
  this.deduplicator = new RequestDeduplicator();
485
504
  this.requestQueue = new RequestQueue(
486
505
  config.maxConcurrentRequests || 10,
487
- config.requestQueueSize || 100
506
+ config.requestQueueSize || 100,
488
507
  );
489
508
  }
490
509
 
@@ -690,7 +709,7 @@ export class HttpService {
690
709
 
691
710
  // Build headers - start with defaults
692
711
  const headers: Record<string, string> = {
693
- 'Accept': 'application/json',
712
+ Accept: 'application/json',
694
713
  };
695
714
 
696
715
  // Only set Content-Type for non-FormData requests (FormData sets it automatically with boundary)
@@ -711,7 +730,9 @@ export class HttpService {
711
730
  // For FormData, explicitly remove Content-Type if user tries to set it
712
731
  // The browser/fetch API will set it automatically with the boundary
713
732
  if (isFormData && key.toLowerCase() === 'content-type') {
714
- this.logger.debug('Ignoring Content-Type header for FormData - will be set automatically');
733
+ this.logger.debug(
734
+ 'Ignoring Content-Type header for FormData - will be set automatically',
735
+ );
715
736
  continue;
716
737
  }
717
738
  headers[key] = value;
@@ -727,8 +748,13 @@ export class HttpService {
727
748
  // `URLSearchParams` is serialised explicitly rather than handed to
728
749
  // `fetch` as-is: RN's fetch does not consistently encode it, and doing
729
750
  // it here keeps the body identical across every platform.
730
- const bodyValue = method !== 'GET' && data
731
- ? (isFormData ? data : isUrlEncoded ? data.toString() : JSON.stringify(data))
751
+ const bodyValue =
752
+ method !== 'GET' && data
753
+ ? isFormData
754
+ ? data
755
+ : isUrlEncoded
756
+ ? data.toString()
757
+ : JSON.stringify(data)
732
758
  : undefined;
733
759
 
734
760
  // React Native FormData workaround:
@@ -737,7 +763,8 @@ export class HttpService {
737
763
  // RN's native XMLHttpRequest handles those descriptors correctly, so we
738
764
  // route multipart uploads through XHR on RN only. JSON, text, etc. still
739
765
  // use fetch on every platform.
740
- const useXhrForUpload = isFormData && isReactNative() && typeof XMLHttpRequest !== 'undefined';
766
+ const useXhrForUpload =
767
+ isFormData && isReactNative() && typeof XMLHttpRequest !== 'undefined';
741
768
 
742
769
  const response = useXhrForUpload
743
770
  ? await this.uploadViaXHR(
@@ -781,7 +808,13 @@ export class HttpService {
781
808
  // queue slot, so a queued retry waits for a slot while holding one.
782
809
  // With every slot held by a 401 (a revoked session under load) no
783
810
  // retry could ever start and the whole client stalled.
784
- return this.request<T>({ ...config, _isAuthRetry: true, retry: false, deduplicate: false, bypassQueue: true });
811
+ return this.request<T>({
812
+ ...config,
813
+ _isAuthRetry: true,
814
+ retry: false,
815
+ deduplicate: false,
816
+ bypassQueue: true,
817
+ });
785
818
  }
786
819
  // Refresh failed or no token — clear tokens
787
820
  this.tokenStore.clearTokens();
@@ -816,7 +849,11 @@ export class HttpService {
816
849
  response?: { status: number; statusText: string; data?: unknown };
817
850
  };
818
851
  error.status = response.status;
819
- error.response = { status: response.status, statusText: response.statusText, data: errorBody };
852
+ error.response = {
853
+ status: response.status,
854
+ statusText: response.statusText,
855
+ data: errorBody,
856
+ };
820
857
  // Only set `code`/`details` when the server actually sent them.
821
858
  // Assigning `undefined` would still create the property, which changes
822
859
  // how `handleHttpError` classifies the error downstream.
@@ -832,7 +869,7 @@ export class HttpService {
832
869
  // Handle different response types (optimized - read response once)
833
870
  const contentType = response.headers.get('content-type');
834
871
  let responseData: unknown;
835
-
872
+
836
873
  if (config.responseType === 'blob') {
837
874
  responseData = await response.blob();
838
875
  } else if (contentType?.includes('application/json')) {
@@ -860,7 +897,13 @@ export class HttpService {
860
897
  throw new Error('Failed to read response from server');
861
898
  }
862
899
  }
863
- } else if (contentType && (contentType.includes('application/octet-stream') || contentType.includes('image/') || contentType.includes('video/') || contentType.includes('audio/'))) {
900
+ } else if (
901
+ contentType &&
902
+ (contentType.includes('application/octet-stream') ||
903
+ contentType.includes('image/') ||
904
+ contentType.includes('video/') ||
905
+ contentType.includes('audio/'))
906
+ ) {
864
907
  // For binary responses (blobs), return the blob directly without unwrapping
865
908
  responseData = await response.blob();
866
909
  } else {
@@ -878,7 +921,11 @@ export class HttpService {
878
921
  const duration = Date.now() - startTime;
879
922
  this.updateMetrics(false, duration);
880
923
  this.config.onRequestEnd?.(url, method, duration, false);
881
- this.config.onRequestError?.(url, method, error instanceof Error ? error : new Error(String(error)));
924
+ this.config.onRequestError?.(
925
+ url,
926
+ method,
927
+ error instanceof Error ? error : new Error(String(error)),
928
+ );
882
929
 
883
930
  // An abort is the one failure whose CAUSE the error cannot carry on its
884
931
  // own: `fetch` reports a caller cancellation and our own timeout as the
@@ -931,7 +978,9 @@ export class HttpService {
931
978
  // Control-plane calls the auth lane depends on (`bypassQueue`, e.g. the
932
979
  // device-secret mint) run DIRECTLY — a queued mint could never acquire a
933
980
  // slot when every slot is parked awaiting it.
934
- config.bypassQueue ? attempt(domain) : this.requestQueue.enqueue(() => attempt(domain), domain);
981
+ config.bypassQueue
982
+ ? attempt(domain)
983
+ : this.requestQueue.enqueue(() => attempt(domain), domain);
935
984
  const execute = (domain: AbortSignal): Promise<T> =>
936
985
  retry
937
986
  ? retryAsync(() => runAttempt(domain), {
@@ -1050,7 +1099,11 @@ export class HttpService {
1050
1099
  }
1051
1100
 
1052
1101
  const onAbort = (): void => {
1053
- try { xhr.abort(); } catch { /* xhr already finished */ }
1102
+ try {
1103
+ xhr.abort();
1104
+ } catch {
1105
+ /* xhr already finished */
1106
+ }
1054
1107
  };
1055
1108
  if (abortSignal.aborted) {
1056
1109
  reject(new DOMException('The user aborted a request.', 'AbortError'));
@@ -1065,11 +1118,13 @@ export class HttpService {
1065
1118
  xhr.onload = (): void => {
1066
1119
  cleanup();
1067
1120
  const responseHeaders = HttpService.parseXHRHeaders(xhr.getAllResponseHeaders());
1068
- resolve(new Response(xhr.responseText, {
1069
- status: xhr.status,
1070
- statusText: xhr.statusText,
1071
- headers: responseHeaders,
1072
- }));
1121
+ resolve(
1122
+ new Response(xhr.responseText, {
1123
+ status: xhr.status,
1124
+ statusText: xhr.statusText,
1125
+ headers: responseHeaders,
1126
+ }),
1127
+ );
1073
1128
  };
1074
1129
  xhr.onerror = (): void => {
1075
1130
  cleanup();
@@ -1200,7 +1255,7 @@ export class HttpService {
1200
1255
  const base = /^https?:\/\//i.test(url)
1201
1256
  ? url
1202
1257
  : `${trimTrailingSlashes(this.baseURL)}/${trimLeadingSlashes(url)}`;
1203
-
1258
+
1204
1259
  if (!params || Object.keys(params).length === 0) {
1205
1260
  return base;
1206
1261
  }
@@ -1511,13 +1566,20 @@ export class HttpService {
1511
1566
  return this.requestRawResponse(config, false);
1512
1567
  }
1513
1568
 
1514
- private async requestRawResponse(config: ResponseRequest, requireAuth: boolean): Promise<Response> {
1569
+ private async requestRawResponse(
1570
+ config: ResponseRequest,
1571
+ requireAuth: boolean,
1572
+ ): Promise<Response> {
1515
1573
  // Validate before obtaining a bearer: an unrelated origin must not trigger
1516
1574
  // an auth mint, even when the trusted transport accepts absolute URLs.
1517
1575
  const target = new URL(this.buildURL(config.url));
1518
1576
  const base = new URL(this.baseURL);
1519
- if (target.origin !== base.origin || !['http:', 'https:'].includes(target.protocol)
1520
- || target.username || target.password) {
1577
+ if (
1578
+ target.origin !== base.origin ||
1579
+ !['http:', 'https:'].includes(target.protocol) ||
1580
+ target.username ||
1581
+ target.password
1582
+ ) {
1521
1583
  throw new Error('Raw response requests must target the configured API origin');
1522
1584
  }
1523
1585
  if (config.signal?.aborted) throw createCancelledError();
@@ -1526,14 +1588,27 @@ export class HttpService {
1526
1588
  const contextToken = this.syncAccessTokenFromProvider();
1527
1589
  const beforeAuthEpoch = this.sessionEpoch;
1528
1590
  const authHeader = await awaitRequestSignal(this.getAuthHeader(), config.signal);
1529
- if (beforeAuthEpoch !== this.sessionEpoch || !sameTokenSession(contextToken, this.tokenStore.getAccessToken())) {
1591
+ if (
1592
+ beforeAuthEpoch !== this.sessionEpoch ||
1593
+ !sameTokenSession(contextToken, this.tokenStore.getAccessToken())
1594
+ ) {
1530
1595
  throw new OxyAuthenticationError('The request session changed', 'AUTH_SESSION_CHANGED');
1531
1596
  }
1532
1597
  if (config.signal?.aborted) throw createCancelledError();
1533
1598
  if (requireAuth && !authHeader) {
1534
- throw new OxyAuthenticationError('An active Oxy session is required for this request', 'AUTH_REQUIRED');
1599
+ throw new OxyAuthenticationError(
1600
+ 'An active Oxy session is required for this request',
1601
+ 'AUTH_REQUIRED',
1602
+ );
1535
1603
  }
1536
- return this.requestResponseAttempt(request, target.href, authHeader, false, this.sessionEpoch, contextToken);
1604
+ return this.requestResponseAttempt(
1605
+ request,
1606
+ target.href,
1607
+ authHeader,
1608
+ false,
1609
+ this.sessionEpoch,
1610
+ contextToken,
1611
+ );
1537
1612
  }
1538
1613
 
1539
1614
  private async requestResponseAttempt(
@@ -1546,7 +1621,10 @@ export class HttpService {
1546
1621
  ): Promise<Response> {
1547
1622
  const assertCurrent = (): void => {
1548
1623
  this.syncAccessTokenFromProvider();
1549
- if (epoch !== this.sessionEpoch || !sameTokenSession(contextToken, this.tokenStore.getAccessToken())) {
1624
+ if (
1625
+ epoch !== this.sessionEpoch ||
1626
+ !sameTokenSession(contextToken, this.tokenStore.getAccessToken())
1627
+ ) {
1550
1628
  throw new OxyAuthenticationError('The request session changed', 'AUTH_SESSION_CHANGED');
1551
1629
  }
1552
1630
  };
@@ -1556,7 +1634,8 @@ export class HttpService {
1556
1634
  const headers = new Headers(config.headers);
1557
1635
  if (!headers.has('Accept')) headers.set('Accept', 'application/json');
1558
1636
  // Never accept ambient credentials or another authority from a caller.
1559
- for (const name of ['Authorization', 'Cookie', 'Cookie2', 'Host', 'Proxy-Authorization']) headers.delete(name);
1637
+ for (const name of ['Authorization', 'Cookie', 'Cookie2', 'Host', 'Proxy-Authorization'])
1638
+ headers.delete(name);
1560
1639
  if (authHeader) headers.set('Authorization', authHeader);
1561
1640
  const edgeRegionHeader = peekBrowserEdgeRegionHeader();
1562
1641
  for (const [name, value] of Object.entries(edgeRegionHeader)) headers.set(name, value);
@@ -1577,21 +1656,47 @@ export class HttpService {
1577
1656
  // multipart bodies keep the platform's existing body serialization.
1578
1657
  if (body && typeof body === 'object' && 'getReader' in body) init.duplex = 'half';
1579
1658
  const response = await (config.fetch ?? globalThis.fetch)(fullUrl, init);
1580
- try { assertCurrent(); } catch (error) { await response.body?.cancel(); throw error; }
1659
+ try {
1660
+ assertCurrent();
1661
+ } catch (error) {
1662
+ await response.body?.cancel();
1663
+ throw error;
1664
+ }
1581
1665
  const replayable = body === undefined || typeof body === 'string';
1582
- if (response.status === 401 && !isAuthRetry && authHeader && replayable && !config.signal?.aborted) {
1666
+ if (
1667
+ response.status === 401 &&
1668
+ !isAuthRetry &&
1669
+ authHeader &&
1670
+ replayable &&
1671
+ !config.signal?.aborted
1672
+ ) {
1583
1673
  let refreshed: string | null;
1584
1674
  try {
1585
- refreshed = await awaitRequestSignal(this.refreshAccessToken('response-401'), config.signal);
1675
+ refreshed = await awaitRequestSignal(
1676
+ this.refreshAccessToken('response-401'),
1677
+ config.signal,
1678
+ );
1586
1679
  } catch (error) {
1587
1680
  void response.body?.cancel().catch(() => undefined);
1588
1681
  throw error;
1589
1682
  }
1590
- try { assertCurrent(); } catch (error) { await response.body?.cancel(); throw error; }
1683
+ try {
1684
+ assertCurrent();
1685
+ } catch (error) {
1686
+ await response.body?.cancel();
1687
+ throw error;
1688
+ }
1591
1689
  if (refreshed) {
1592
1690
  await response.body?.cancel();
1593
1691
  if (config.signal?.aborted) throw createCancelledError();
1594
- return this.requestResponseAttempt(config, fullUrl, `Bearer ${refreshed}`, true, epoch, contextToken);
1692
+ return this.requestResponseAttempt(
1693
+ config,
1694
+ fullUrl,
1695
+ `Bearer ${refreshed}`,
1696
+ true,
1697
+ epoch,
1698
+ contextToken,
1699
+ );
1595
1700
  }
1596
1701
  this.clearTokens();
1597
1702
  }
@@ -1604,11 +1709,15 @@ export class HttpService {
1604
1709
  const duration = Date.now() - startTime;
1605
1710
  this.updateMetrics(false, duration);
1606
1711
  this.config.onRequestEnd?.(config.url, config.method, duration, false);
1607
- const normalizedError = config.signal?.aborted || isCancelledError(error)
1608
- ? createCancelledError()
1609
- : error instanceof Error ? error : new Error(String(error));
1712
+ const normalizedError =
1713
+ config.signal?.aborted || isCancelledError(error)
1714
+ ? createCancelledError()
1715
+ : error instanceof Error
1716
+ ? error
1717
+ : new Error(String(error));
1610
1718
  this.config.onRequestError?.(config.url, config.method, normalizedError);
1611
- if (isCancelledError(normalizedError) || normalizedError instanceof OxyAuthenticationError) throw normalizedError;
1719
+ if (isCancelledError(normalizedError) || normalizedError instanceof OxyAuthenticationError)
1720
+ throw normalizedError;
1612
1721
  throw handleHttpError(normalizedError);
1613
1722
  }
1614
1723
  }
@@ -1618,19 +1727,34 @@ export class HttpService {
1618
1727
  return this.request<T>({ method: 'GET', url, ...config });
1619
1728
  }
1620
1729
 
1621
- async post<T = unknown>(url: string, data?: unknown, config?: Omit<RequestConfig, 'method' | 'url' | 'data'>): Promise<T> {
1730
+ async post<T = unknown>(
1731
+ url: string,
1732
+ data?: unknown,
1733
+ config?: Omit<RequestConfig, 'method' | 'url' | 'data'>,
1734
+ ): Promise<T> {
1622
1735
  return this.request<T>({ method: 'POST', url, data, ...config });
1623
1736
  }
1624
1737
 
1625
- async put<T = unknown>(url: string, data?: unknown, config?: Omit<RequestConfig, 'method' | 'url' | 'data'>): Promise<T> {
1738
+ async put<T = unknown>(
1739
+ url: string,
1740
+ data?: unknown,
1741
+ config?: Omit<RequestConfig, 'method' | 'url' | 'data'>,
1742
+ ): Promise<T> {
1626
1743
  return this.request<T>({ method: 'PUT', url, data, ...config });
1627
1744
  }
1628
1745
 
1629
- async patch<T = unknown>(url: string, data?: unknown, config?: Omit<RequestConfig, 'method' | 'url' | 'data'>): Promise<T> {
1746
+ async patch<T = unknown>(
1747
+ url: string,
1748
+ data?: unknown,
1749
+ config?: Omit<RequestConfig, 'method' | 'url' | 'data'>,
1750
+ ): Promise<T> {
1630
1751
  return this.request<T>({ method: 'PATCH', url, data, ...config });
1631
1752
  }
1632
1753
 
1633
- async delete<T = unknown>(url: string, config?: Omit<RequestConfig, 'method' | 'url'>): Promise<T> {
1754
+ async delete<T = unknown>(
1755
+ url: string,
1756
+ config?: Omit<RequestConfig, 'method' | 'url'>,
1757
+ ): Promise<T> {
1634
1758
  return this.request<T>({ method: 'DELETE', url, ...config });
1635
1759
  }
1636
1760
 
@@ -1794,7 +1918,13 @@ export class HttpService {
1794
1918
  * per resource.
1795
1919
  * @returns Number of entries deleted
1796
1920
  */
1797
- invalidateCache({ keys = [], prefixes = [] }: { keys?: readonly string[]; prefixes?: readonly string[] }): number {
1921
+ invalidateCache({
1922
+ keys = [],
1923
+ prefixes = [],
1924
+ }: {
1925
+ keys?: readonly string[];
1926
+ prefixes?: readonly string[];
1927
+ }): number {
1798
1928
  if (keys.length === 0 && prefixes.length === 0) return 0;
1799
1929
  const exact = new Set(keys);
1800
1930
  const delim = HttpService.CACHE_IDENTITY_DELIM;
@@ -54,7 +54,12 @@ export class AssetUrlResolutionError extends Error {
54
54
  */
55
55
  public readonly cause?: unknown;
56
56
 
57
- constructor(fileId: string, variant: string | undefined, status: number | undefined, cause?: unknown) {
57
+ constructor(
58
+ fileId: string,
59
+ variant: string | undefined,
60
+ status: number | undefined,
61
+ cause?: unknown,
62
+ ) {
58
63
  const variantSuffix = variant ? ` (variant "${variant}")` : '';
59
64
  const statusSuffix = typeof status === 'number' ? ` — status ${status}` : '';
60
65
  super(`Could not resolve a download URL for asset "${fileId}"${variantSuffix}${statusSuffix}`);
@@ -152,13 +157,12 @@ export class OxyAuthenticationTimeoutError extends OxyAuthenticationError {
152
157
  super(
153
158
  `Authentication timeout (${timeoutMs}ms): ${operationName} requires user authentication. Please ensure the user is logged in before calling this method.`,
154
159
  'AUTH_TIMEOUT',
155
- 408
160
+ 408,
156
161
  );
157
162
  this.name = 'OxyAuthenticationTimeoutError';
158
163
  }
159
164
  }
160
165
 
161
-
162
166
  /**
163
167
  * The one error every `OxyServices` call rejects with.
164
168
  *
@@ -98,7 +98,12 @@ export class OxyServices {
98
98
  * built on, for the routes no namespace covers yet. GET sends `data` as the
99
99
  * query string, every other method as the body. Rejects with `OxyApiError`.
100
100
  */
101
- async request<T>(method: HttpMethod, url: string, data?: unknown, options: RequestOptions = {}): Promise<T> {
101
+ async request<T>(
102
+ method: HttpMethod,
103
+ url: string,
104
+ data?: unknown,
105
+ options: RequestOptions = {},
106
+ ): Promise<T> {
102
107
  try {
103
108
  return await this.http.request<T>({
104
109
  method,
@@ -303,4 +308,3 @@ export class OxyServices {
303
308
  return this._contacts;
304
309
  }
305
310
  }
306
-