@oxy.so/core 1.18.0 → 3.0.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 (662) hide show
  1. package/README.md +13 -7
  2. package/dist/cjs/HttpService.js +189 -112
  3. package/dist/cjs/OxyServices.errors.js +48 -1
  4. package/dist/cjs/OxyServices.js +263 -60
  5. package/dist/cjs/api/accounts.js +231 -0
  6. package/dist/cjs/api/agency.js +102 -0
  7. package/dist/cjs/api/appData.js +45 -0
  8. package/dist/cjs/api/apps.js +197 -0
  9. package/dist/cjs/api/assets.js +329 -0
  10. package/dist/cjs/api/auth.js +900 -0
  11. package/dist/cjs/api/billing.js +44 -0
  12. package/dist/cjs/api/civic.js +289 -0
  13. package/dist/cjs/api/contacts.js +16 -0
  14. package/dist/cjs/api/devices.js +351 -0
  15. package/dist/cjs/api/follows.js +240 -0
  16. package/dist/cjs/api/identity.js +569 -0
  17. package/dist/cjs/api/linkedAccounts.js +48 -0
  18. package/dist/cjs/api/nodes.js +75 -0
  19. package/dist/cjs/api/notifications.js +75 -0
  20. package/dist/cjs/api/privacy.js +105 -0
  21. package/dist/cjs/api/reputation.js +74 -0
  22. package/dist/cjs/api/session.js +177 -0
  23. package/dist/cjs/api/store.js +199 -0
  24. package/dist/cjs/api/topics.js +66 -0
  25. package/dist/cjs/api/users.js +309 -0
  26. package/dist/cjs/boot/sessionColdBoot.js +4 -4
  27. package/dist/cjs/civic/index.js +16 -0
  28. package/dist/cjs/civic/payloads.js +156 -0
  29. package/dist/cjs/client/context.js +2 -0
  30. package/dist/cjs/crypto/identityLink.js +5 -5
  31. package/dist/cjs/crypto/index.js +44 -0
  32. package/dist/cjs/crypto/internal.js +37 -0
  33. package/dist/cjs/crypto/keyManager.js +2 -2
  34. package/dist/cjs/crypto/polyfill.js +9 -80
  35. package/dist/cjs/crypto/recoveryPhrase.js +1 -0
  36. package/dist/cjs/crypto/registrationPow.js +1 -1
  37. package/dist/cjs/crypto/signatureService.js +1 -0
  38. package/dist/cjs/i18n/accountCategoryLabels.js +3 -3
  39. package/dist/cjs/i18n/accountRoleLabels.js +7 -7
  40. package/dist/cjs/i18n/index.js +130 -52
  41. package/dist/cjs/i18n/locales/{ar-SA.json → ar-SA.js} +134 -52
  42. package/dist/cjs/i18n/locales/{ca-ES.json → ca-ES.js} +134 -52
  43. package/dist/{esm/i18n/locales/de-DE.json → cjs/i18n/locales/de-DE.js} +136 -54
  44. package/dist/{esm/i18n/locales/en-US.json → cjs/i18n/locales/en-US.js} +163 -245
  45. package/dist/{esm/i18n/locales/es-ES.json → cjs/i18n/locales/es-ES.js} +163 -245
  46. package/dist/cjs/i18n/locales/{fr-FR.json → fr-FR.js} +134 -52
  47. package/dist/cjs/i18n/locales/{it-IT.json → it-IT.js} +134 -52
  48. package/dist/{esm/i18n/locales/ja-JP.json → cjs/i18n/locales/ja-JP.js} +134 -52
  49. package/dist/cjs/i18n/locales/{ko-KR.json → ko-KR.js} +134 -52
  50. package/dist/{esm/i18n/locales/pt-PT.json → cjs/i18n/locales/pt-PT.js} +136 -54
  51. package/dist/{esm/i18n/locales/zh-CN.json → cjs/i18n/locales/zh-CN.js} +135 -53
  52. package/dist/cjs/i18n/reputationCategoryLabels.js +2 -2
  53. package/dist/cjs/i18n/trustTierLabels.js +2 -2
  54. package/dist/cjs/index.js +55 -263
  55. package/dist/cjs/inference/index.js +21 -0
  56. package/dist/cjs/server/OxyServer.js +521 -0
  57. package/dist/cjs/server/auth.js +2 -2
  58. package/dist/cjs/server/index.js +23 -6
  59. package/dist/cjs/server/middleware.js +1154 -0
  60. package/dist/cjs/server/namespaces.js +214 -0
  61. package/dist/cjs/server/rateLimit.js +2 -2
  62. package/dist/cjs/server/requesterAssertion.js +5 -5
  63. package/dist/cjs/server/securityHeaders.js +3 -3
  64. package/dist/cjs/server/traffic.js +7 -6
  65. package/dist/cjs/server/trafficNodeHttp.js +9 -3
  66. package/dist/cjs/server/userInvalidation.js +5 -5
  67. package/dist/cjs/session/accountDialogController.js +23 -23
  68. package/dist/cjs/session/authStateStore.js +2 -2
  69. package/dist/cjs/session/identitySession.js +3 -3
  70. package/dist/cjs/session/index.js +131 -0
  71. package/dist/cjs/session/refresh.js +37 -30
  72. package/dist/cjs/session/sessionClientHost.js +5 -5
  73. package/dist/cjs/session/sharedDeviceCredential.js +3 -2
  74. package/dist/cjs/shared/utils/networkUtils.js +2 -2
  75. package/dist/cjs/utils/accountCacheSweep.js +11 -15
  76. package/dist/cjs/utils/asyncUtils.js +22 -163
  77. package/dist/cjs/utils/authHelpers.js +2 -2
  78. package/dist/cjs/utils/authWebUrl.js +3 -4
  79. package/dist/cjs/utils/avatarUtils.js +2 -2
  80. package/dist/cjs/utils/cache.js +32 -2
  81. package/dist/cjs/utils/cacheKey.js +5 -10
  82. package/dist/cjs/utils/deviceManager.js +17 -16
  83. package/dist/cjs/utils/edgeRegion.js +2 -3
  84. package/dist/cjs/utils/identityCacheSweep.js +6 -10
  85. package/dist/cjs/utils/oxyServiceEnvironment.js +3 -7
  86. package/dist/cjs/utils/requestUtils.js +40 -33
  87. package/dist/cjs/utils/sessionUtils.js +0 -2
  88. package/dist/cjs/utils/tokenClaims.js +34 -0
  89. package/dist/esm/HttpService.js +190 -113
  90. package/dist/esm/OxyServices.errors.js +45 -0
  91. package/dist/esm/OxyServices.js +262 -57
  92. package/dist/esm/api/accounts.js +218 -0
  93. package/dist/esm/api/agency.js +95 -0
  94. package/dist/esm/api/appData.js +40 -0
  95. package/dist/esm/api/apps.js +191 -0
  96. package/dist/esm/api/assets.js +324 -0
  97. package/dist/esm/api/auth.js +858 -0
  98. package/dist/esm/api/billing.js +40 -0
  99. package/dist/esm/api/civic.js +250 -0
  100. package/dist/esm/api/contacts.js +12 -0
  101. package/dist/esm/api/devices.js +346 -0
  102. package/dist/esm/api/follows.js +236 -0
  103. package/dist/esm/api/identity.js +527 -0
  104. package/dist/esm/api/linkedAccounts.js +44 -0
  105. package/dist/esm/api/nodes.js +71 -0
  106. package/dist/esm/api/notifications.js +71 -0
  107. package/dist/esm/api/privacy.js +101 -0
  108. package/dist/esm/api/reputation.js +70 -0
  109. package/dist/esm/api/session.js +173 -0
  110. package/dist/esm/api/store.js +192 -0
  111. package/dist/esm/api/topics.js +62 -0
  112. package/dist/esm/api/users.js +272 -0
  113. package/dist/esm/boot/sessionColdBoot.js +4 -4
  114. package/dist/esm/civic/index.js +10 -0
  115. package/dist/esm/civic/payloads.js +118 -0
  116. package/dist/esm/client/context.js +1 -0
  117. package/dist/esm/crypto/identityLink.js +5 -5
  118. package/dist/esm/crypto/index.js +24 -0
  119. package/dist/esm/crypto/internal.js +19 -0
  120. package/dist/esm/crypto/keyManager.js +2 -2
  121. package/dist/esm/crypto/polyfill.js +10 -81
  122. package/dist/esm/crypto/recoveryPhrase.js +1 -0
  123. package/dist/esm/crypto/registrationPow.js +1 -1
  124. package/dist/esm/crypto/signatureService.js +1 -0
  125. package/dist/esm/i18n/accountCategoryLabels.js +2 -2
  126. package/dist/esm/i18n/accountRoleLabels.js +1 -1
  127. package/dist/esm/i18n/index.js +93 -52
  128. package/dist/esm/i18n/locales/{ar-SA.json → ar-SA.js} +132 -52
  129. package/dist/esm/i18n/locales/{ca-ES.json → ca-ES.js} +132 -52
  130. package/dist/{cjs/i18n/locales/de-DE.json → esm/i18n/locales/de-DE.js} +134 -54
  131. package/dist/{cjs/i18n/locales/en-US.json → esm/i18n/locales/en-US.js} +161 -245
  132. package/dist/{cjs/i18n/locales/es-ES.json → esm/i18n/locales/es-ES.js} +161 -245
  133. package/dist/esm/i18n/locales/{fr-FR.json → fr-FR.js} +132 -52
  134. package/dist/esm/i18n/locales/{it-IT.json → it-IT.js} +132 -52
  135. package/dist/{cjs/i18n/locales/ja-JP.json → esm/i18n/locales/ja-JP.js} +132 -52
  136. package/dist/esm/i18n/locales/{ko-KR.json → ko-KR.js} +132 -52
  137. package/dist/{cjs/i18n/locales/pt-PT.json → esm/i18n/locales/pt-PT.js} +134 -54
  138. package/dist/{cjs/i18n/locales/zh-CN.json → esm/i18n/locales/zh-CN.js} +133 -53
  139. package/dist/esm/i18n/reputationCategoryLabels.js +1 -1
  140. package/dist/esm/i18n/trustTierLabels.js +1 -1
  141. package/dist/esm/index.js +30 -166
  142. package/dist/esm/inference/index.js +13 -0
  143. package/dist/esm/server/OxyServer.js +516 -0
  144. package/dist/esm/server/auth.js +2 -2
  145. package/dist/esm/server/index.js +10 -5
  146. package/dist/esm/server/middleware.js +1147 -0
  147. package/dist/esm/server/namespaces.js +206 -0
  148. package/dist/esm/server/rateLimit.js +2 -2
  149. package/dist/esm/server/requesterAssertion.js +5 -5
  150. package/dist/esm/server/securityHeaders.js +3 -3
  151. package/dist/esm/server/traffic.js +7 -6
  152. package/dist/esm/server/trafficNodeHttp.js +9 -3
  153. package/dist/esm/server/userInvalidation.js +5 -5
  154. package/dist/esm/session/accountDialogController.js +23 -23
  155. package/dist/esm/session/authStateStore.js +2 -2
  156. package/dist/esm/session/identitySession.js +3 -3
  157. package/dist/esm/session/index.js +82 -0
  158. package/dist/esm/session/refresh.js +37 -30
  159. package/dist/esm/session/sessionClientHost.js +5 -5
  160. package/dist/esm/session/sharedDeviceCredential.js +3 -2
  161. package/dist/esm/shared/utils/networkUtils.js +2 -2
  162. package/dist/esm/utils/accountCacheSweep.js +11 -15
  163. package/dist/esm/utils/asyncUtils.js +22 -151
  164. package/dist/esm/utils/authHelpers.js +2 -2
  165. package/dist/esm/utils/authWebUrl.js +3 -4
  166. package/dist/esm/utils/avatarUtils.js +2 -2
  167. package/dist/esm/utils/cache.js +32 -2
  168. package/dist/esm/utils/cacheKey.js +5 -10
  169. package/dist/esm/utils/deviceManager.js +17 -16
  170. package/dist/esm/utils/edgeRegion.js +1 -2
  171. package/dist/esm/utils/identityCacheSweep.js +6 -10
  172. package/dist/esm/utils/oxyServiceEnvironment.js +3 -7
  173. package/dist/esm/utils/requestUtils.js +40 -33
  174. package/dist/esm/utils/sessionUtils.js +0 -2
  175. package/dist/esm/utils/tokenClaims.js +31 -0
  176. package/dist/types/HttpService.d.ts +47 -9
  177. package/dist/types/OxyServices.d.ts +160 -131
  178. package/dist/types/OxyServices.errors.d.ts +42 -0
  179. package/dist/types/api/accounts.d.ts +415 -0
  180. package/dist/types/api/agency.d.ts +135 -0
  181. package/dist/types/api/appData.d.ts +27 -0
  182. package/dist/types/api/apps.d.ts +433 -0
  183. package/dist/types/api/assets.d.ts +174 -0
  184. package/dist/types/api/auth.d.ts +766 -0
  185. package/dist/types/api/billing.d.ts +113 -0
  186. package/dist/types/api/civic.d.ts +203 -0
  187. package/dist/types/api/contacts.d.ts +31 -0
  188. package/{src/mixins/OxyServices.deviceBoot.ts → dist/types/api/devices.d.ts} +130 -110
  189. package/dist/types/api/follows.d.ts +236 -0
  190. package/dist/types/api/identity.d.ts +275 -0
  191. package/dist/types/api/linkedAccounts.d.ts +48 -0
  192. package/dist/types/api/nodes.d.ts +102 -0
  193. package/dist/types/api/notifications.d.ts +77 -0
  194. package/dist/types/api/privacy.d.ts +43 -0
  195. package/dist/types/api/reputation.d.ts +50 -0
  196. package/dist/types/api/session.d.ts +85 -0
  197. package/dist/types/api/store.d.ts +278 -0
  198. package/dist/types/api/topics.d.ts +34 -0
  199. package/dist/types/api/users.d.ts +134 -0
  200. package/dist/types/boot/sessionColdBoot.d.ts +1 -1
  201. package/dist/types/civic/index.d.ts +10 -0
  202. package/dist/types/civic/payloads.d.ts +83 -0
  203. package/dist/types/client/context.d.ts +33 -0
  204. package/dist/types/crypto/identityLink.d.ts +5 -5
  205. package/dist/types/crypto/index.d.ts +24 -0
  206. package/dist/types/crypto/internal.d.ts +19 -0
  207. package/dist/types/crypto/polyfill.d.ts +6 -9
  208. package/dist/types/crypto/registrationPow.d.ts +1 -1
  209. package/dist/types/i18n/accountCategoryLabels.d.ts +1 -1
  210. package/dist/types/i18n/accountRoleLabels.d.ts +1 -1
  211. package/dist/types/i18n/index.d.ts +20 -1
  212. package/dist/types/i18n/locales/ar-SA.d.ts +386 -0
  213. package/dist/types/i18n/locales/ca-ES.d.ts +386 -0
  214. package/dist/types/i18n/locales/de-DE.d.ts +386 -0
  215. package/dist/types/i18n/locales/en-US.d.ts +2034 -0
  216. package/dist/types/i18n/locales/es-ES.d.ts +2034 -0
  217. package/dist/types/i18n/locales/fr-FR.d.ts +386 -0
  218. package/dist/types/i18n/locales/it-IT.d.ts +386 -0
  219. package/dist/types/i18n/locales/ja-JP.d.ts +386 -0
  220. package/dist/types/i18n/locales/ko-KR.d.ts +386 -0
  221. package/dist/types/i18n/locales/pt-PT.d.ts +386 -0
  222. package/dist/types/i18n/locales/zh-CN.d.ts +386 -0
  223. package/dist/types/index.d.ts +46 -95
  224. package/dist/types/inference/index.d.ts +22 -0
  225. package/dist/types/models/interfaces.d.ts +1 -1
  226. package/dist/types/server/OxyServer.d.ts +183 -0
  227. package/dist/types/server/auth.d.ts +10 -7
  228. package/dist/types/server/index.d.ts +10 -4
  229. package/dist/types/server/middleware.d.ts +291 -0
  230. package/dist/types/server/namespaces.d.ts +98 -0
  231. package/dist/types/server/rateLimit.d.ts +7 -5
  232. package/dist/types/server/requesterAssertion.d.ts +14 -11
  233. package/dist/types/server/securityHeaders.d.ts +4 -5
  234. package/dist/types/server/userInvalidation.d.ts +10 -8
  235. package/dist/types/session/accountDelegationAccess.d.ts +1 -1
  236. package/dist/types/session/accountDialogController.d.ts +8 -8
  237. package/dist/types/session/accountSwitchTargets.d.ts +1 -1
  238. package/dist/types/session/authStateStore.d.ts +7 -6
  239. package/dist/types/session/index.d.ts +40 -0
  240. package/dist/types/utils/accountCacheSweep.d.ts +7 -10
  241. package/dist/types/utils/apiUtils.d.ts +3 -3
  242. package/dist/types/utils/asyncUtils.d.ts +11 -58
  243. package/dist/types/utils/authWebUrl.d.ts +3 -4
  244. package/dist/types/utils/avatarUtils.d.ts +5 -6
  245. package/dist/types/utils/cache.d.ts +11 -3
  246. package/dist/types/utils/commonsApproval.d.ts +1 -1
  247. package/dist/types/utils/edgeRegion.d.ts +1 -2
  248. package/dist/types/utils/identityCacheSweep.d.ts +6 -4
  249. package/dist/types/utils/oauthPkce.d.ts +2 -2
  250. package/dist/types/utils/oxyServiceEnvironment.d.ts +3 -7
  251. package/dist/types/utils/requestUtils.d.ts +18 -14
  252. package/dist/types/utils/tokenClaims.d.ts +9 -0
  253. package/package.json +68 -7
  254. package/src/HttpService.ts +201 -132
  255. package/src/OxyServices.errors.ts +73 -0
  256. package/src/OxyServices.ts +289 -164
  257. package/src/api/accounts.ts +579 -0
  258. package/src/api/agency.ts +277 -0
  259. package/src/api/appData.ts +63 -0
  260. package/src/api/apps.ts +596 -0
  261. package/src/api/assets.ts +416 -0
  262. package/src/api/auth.ts +1457 -0
  263. package/src/api/billing.ts +144 -0
  264. package/src/api/civic.ts +428 -0
  265. package/src/api/contacts.ts +41 -0
  266. package/src/api/devices.ts +438 -0
  267. package/src/api/follows.ts +414 -0
  268. package/src/api/identity.ts +727 -0
  269. package/src/api/linkedAccounts.ts +78 -0
  270. package/src/api/nodes.ts +169 -0
  271. package/src/api/notifications.ts +135 -0
  272. package/src/api/privacy.ts +120 -0
  273. package/src/api/reputation.ts +134 -0
  274. package/src/api/session.ts +210 -0
  275. package/src/api/store.ts +435 -0
  276. package/src/api/topics.ts +83 -0
  277. package/src/api/users.ts +357 -0
  278. package/src/boot/sessionColdBoot.ts +4 -4
  279. package/src/civic/index.ts +12 -0
  280. package/src/civic/payloads.ts +175 -0
  281. package/src/client/context.ts +34 -0
  282. package/src/crypto/identityLink.ts +5 -5
  283. package/src/crypto/index.ts +39 -0
  284. package/src/crypto/internal.ts +20 -0
  285. package/src/crypto/keyManager.ts +2 -2
  286. package/src/crypto/polyfill.ts +9 -89
  287. package/src/crypto/recoveryPhrase.ts +1 -0
  288. package/src/crypto/registrationPow.ts +1 -1
  289. package/src/crypto/signatureService.ts +1 -0
  290. package/src/i18n/accountCategoryLabels.ts +2 -2
  291. package/src/i18n/accountRoleLabels.ts +2 -2
  292. package/src/i18n/index.ts +105 -54
  293. package/src/i18n/locales/{ar-SA.json → ar-SA.ts} +132 -52
  294. package/src/i18n/locales/{ca-ES.json → ca-ES.ts} +132 -52
  295. package/{dist/cjs/i18n/locales/locales/de-DE.json → src/i18n/locales/de-DE.ts} +134 -54
  296. package/src/i18n/locales/{en-US.json → en-US.ts} +161 -245
  297. package/{dist/cjs/i18n/locales/locales/es-ES.json → src/i18n/locales/es-ES.ts} +161 -245
  298. package/src/i18n/locales/{fr-FR.json → fr-FR.ts} +132 -52
  299. package/src/i18n/locales/{it-IT.json → it-IT.ts} +132 -52
  300. package/{dist/cjs/i18n/locales/locales/ja-JP.json → src/i18n/locales/ja-JP.ts} +132 -52
  301. package/src/i18n/locales/{ko-KR.json → ko-KR.ts} +132 -52
  302. package/src/i18n/locales/{pt-PT.json → pt-PT.ts} +134 -54
  303. package/src/i18n/locales/{zh-CN.json → zh-CN.ts} +133 -53
  304. package/src/i18n/reputationCategoryLabels.ts +1 -1
  305. package/src/i18n/trustTierLabels.ts +1 -1
  306. package/src/index.ts +170 -501
  307. package/src/inference/index.ts +48 -0
  308. package/src/models/interfaces.ts +1 -1
  309. package/src/server/OxyServer.ts +637 -0
  310. package/src/server/auth.ts +12 -8
  311. package/src/server/index.ts +28 -5
  312. package/src/server/middleware.ts +1520 -0
  313. package/src/server/namespaces.ts +257 -0
  314. package/src/server/rateLimit.ts +10 -9
  315. package/src/server/requesterAssertion.ts +13 -10
  316. package/src/server/securityHeaders.ts +7 -8
  317. package/src/server/traffic.ts +6 -6
  318. package/src/server/trafficNodeHttp.ts +7 -3
  319. package/src/server/userInvalidation.ts +9 -9
  320. package/src/session/accountDelegationAccess.ts +1 -1
  321. package/src/session/accountDialogController.ts +24 -24
  322. package/src/session/accountSwitchTargets.ts +1 -1
  323. package/src/session/authStateStore.ts +9 -8
  324. package/src/session/identitySession.ts +3 -3
  325. package/src/session/index.ts +210 -0
  326. package/src/session/refresh.ts +36 -30
  327. package/src/session/sessionClientHost.ts +5 -5
  328. package/src/session/sharedDeviceCredential.ts +3 -2
  329. package/src/shared/utils/networkUtils.ts +2 -2
  330. package/src/utils/accountCacheSweep.ts +11 -15
  331. package/src/utils/apiUtils.ts +3 -3
  332. package/src/utils/asyncUtils.ts +38 -235
  333. package/src/utils/authHelpers.ts +2 -2
  334. package/src/utils/authWebUrl.ts +3 -4
  335. package/src/utils/avatarUtils.ts +4 -7
  336. package/src/utils/cache.ts +36 -5
  337. package/src/utils/cacheKey.ts +5 -9
  338. package/src/utils/commonsApproval.ts +1 -1
  339. package/src/utils/deviceManager.ts +17 -16
  340. package/src/utils/edgeRegion.ts +1 -2
  341. package/src/utils/identityCacheSweep.ts +7 -12
  342. package/src/utils/oauthPkce.ts +2 -2
  343. package/src/utils/oxyServiceEnvironment.ts +3 -7
  344. package/src/utils/requestUtils.ts +48 -44
  345. package/src/utils/sessionUtils.ts +0 -2
  346. package/src/utils/tokenClaims.ts +38 -0
  347. package/dist/cjs/.tsbuildinfo +0 -1
  348. package/dist/cjs/OxyServices.base.js +0 -392
  349. package/dist/cjs/i18n/locales/locales/ar-SA.json +0 -306
  350. package/dist/cjs/i18n/locales/locales/ca-ES.json +0 -306
  351. package/dist/cjs/i18n/locales/locales/en-US.json +0 -2127
  352. package/dist/cjs/i18n/locales/locales/fr-FR.json +0 -306
  353. package/dist/cjs/i18n/locales/locales/it-IT.json +0 -306
  354. package/dist/cjs/i18n/locales/locales/ko-KR.json +0 -306
  355. package/dist/cjs/i18n/locales/locales/pt-PT.json +0 -306
  356. package/dist/cjs/i18n/locales/locales/zh-CN.json +0 -306
  357. package/dist/cjs/mixins/OxyServices.accounts.js +0 -555
  358. package/dist/cjs/mixins/OxyServices.agency.js +0 -154
  359. package/dist/cjs/mixins/OxyServices.analytics.js +0 -49
  360. package/dist/cjs/mixins/OxyServices.appData.js +0 -108
  361. package/dist/cjs/mixins/OxyServices.assets.js +0 -854
  362. package/dist/cjs/mixins/OxyServices.auth.js +0 -1440
  363. package/dist/cjs/mixins/OxyServices.chains.js +0 -73
  364. package/dist/cjs/mixins/OxyServices.civic.js +0 -611
  365. package/dist/cjs/mixins/OxyServices.connectedApps.js +0 -95
  366. package/dist/cjs/mixins/OxyServices.contacts.js +0 -50
  367. package/dist/cjs/mixins/OxyServices.deviceBoot.js +0 -191
  368. package/dist/cjs/mixins/OxyServices.devices.js +0 -116
  369. package/dist/cjs/mixins/OxyServices.features.js +0 -335
  370. package/dist/cjs/mixins/OxyServices.followGraph.js +0 -221
  371. package/dist/cjs/mixins/OxyServices.identity.js +0 -562
  372. package/dist/cjs/mixins/OxyServices.identityBackup.js +0 -172
  373. package/dist/cjs/mixins/OxyServices.inference.js +0 -59
  374. package/dist/cjs/mixins/OxyServices.language.js +0 -125
  375. package/dist/cjs/mixins/OxyServices.linkedAccounts.js +0 -79
  376. package/dist/cjs/mixins/OxyServices.location.js +0 -43
  377. package/dist/cjs/mixins/OxyServices.nodes.js +0 -175
  378. package/dist/cjs/mixins/OxyServices.notifications.js +0 -63
  379. package/dist/cjs/mixins/OxyServices.payment.js +0 -158
  380. package/dist/cjs/mixins/OxyServices.privacy.js +0 -199
  381. package/dist/cjs/mixins/OxyServices.reputation.js +0 -289
  382. package/dist/cjs/mixins/OxyServices.security.js +0 -89
  383. package/dist/cjs/mixins/OxyServices.store.js +0 -266
  384. package/dist/cjs/mixins/OxyServices.topics.js +0 -137
  385. package/dist/cjs/mixins/OxyServices.user.js +0 -954
  386. package/dist/cjs/mixins/OxyServices.utility.js +0 -1402
  387. package/dist/cjs/mixins/index.js +0 -136
  388. package/dist/cjs/mixins/mixinHelpers.js +0 -53
  389. package/dist/cjs/utils/webauthnOrigin.js +0 -51
  390. package/dist/esm/.tsbuildinfo +0 -1
  391. package/dist/esm/OxyServices.base.js +0 -388
  392. package/dist/esm/i18n/locales/locales/ar-SA.json +0 -306
  393. package/dist/esm/i18n/locales/locales/ca-ES.json +0 -306
  394. package/dist/esm/i18n/locales/locales/de-DE.json +0 -306
  395. package/dist/esm/i18n/locales/locales/en-US.json +0 -2127
  396. package/dist/esm/i18n/locales/locales/es-ES.json +0 -2127
  397. package/dist/esm/i18n/locales/locales/fr-FR.json +0 -306
  398. package/dist/esm/i18n/locales/locales/it-IT.json +0 -306
  399. package/dist/esm/i18n/locales/locales/ja-JP.json +0 -306
  400. package/dist/esm/i18n/locales/locales/ko-KR.json +0 -306
  401. package/dist/esm/i18n/locales/locales/pt-PT.json +0 -306
  402. package/dist/esm/i18n/locales/locales/zh-CN.json +0 -306
  403. package/dist/esm/mixins/OxyServices.accounts.js +0 -543
  404. package/dist/esm/mixins/OxyServices.agency.js +0 -151
  405. package/dist/esm/mixins/OxyServices.analytics.js +0 -46
  406. package/dist/esm/mixins/OxyServices.appData.js +0 -103
  407. package/dist/esm/mixins/OxyServices.assets.js +0 -851
  408. package/dist/esm/mixins/OxyServices.auth.js +0 -1400
  409. package/dist/esm/mixins/OxyServices.chains.js +0 -70
  410. package/dist/esm/mixins/OxyServices.civic.js +0 -605
  411. package/dist/esm/mixins/OxyServices.connectedApps.js +0 -92
  412. package/dist/esm/mixins/OxyServices.contacts.js +0 -47
  413. package/dist/esm/mixins/OxyServices.deviceBoot.js +0 -186
  414. package/dist/esm/mixins/OxyServices.devices.js +0 -113
  415. package/dist/esm/mixins/OxyServices.features.js +0 -332
  416. package/dist/esm/mixins/OxyServices.followGraph.js +0 -218
  417. package/dist/esm/mixins/OxyServices.identity.js +0 -558
  418. package/dist/esm/mixins/OxyServices.identityBackup.js +0 -169
  419. package/dist/esm/mixins/OxyServices.inference.js +0 -56
  420. package/dist/esm/mixins/OxyServices.language.js +0 -122
  421. package/dist/esm/mixins/OxyServices.linkedAccounts.js +0 -76
  422. package/dist/esm/mixins/OxyServices.location.js +0 -40
  423. package/dist/esm/mixins/OxyServices.nodes.js +0 -172
  424. package/dist/esm/mixins/OxyServices.notifications.js +0 -60
  425. package/dist/esm/mixins/OxyServices.payment.js +0 -155
  426. package/dist/esm/mixins/OxyServices.privacy.js +0 -196
  427. package/dist/esm/mixins/OxyServices.reputation.js +0 -286
  428. package/dist/esm/mixins/OxyServices.security.js +0 -86
  429. package/dist/esm/mixins/OxyServices.store.js +0 -263
  430. package/dist/esm/mixins/OxyServices.topics.js +0 -134
  431. package/dist/esm/mixins/OxyServices.user.js +0 -951
  432. package/dist/esm/mixins/OxyServices.utility.js +0 -1397
  433. package/dist/esm/mixins/index.js +0 -133
  434. package/dist/esm/mixins/mixinHelpers.js +0 -48
  435. package/dist/esm/utils/webauthnOrigin.js +0 -48
  436. package/dist/types/.tsbuildinfo +0 -1
  437. package/dist/types/OxyServices.base.d.ts +0 -189
  438. package/dist/types/mixins/OxyServices.accounts.d.ts +0 -868
  439. package/dist/types/mixins/OxyServices.agency.d.ts +0 -176
  440. package/dist/types/mixins/OxyServices.analytics.d.ts +0 -72
  441. package/dist/types/mixins/OxyServices.appData.d.ts +0 -108
  442. package/dist/types/mixins/OxyServices.assets.d.ts +0 -371
  443. package/dist/types/mixins/OxyServices.auth.d.ts +0 -965
  444. package/dist/types/mixins/OxyServices.chains.d.ts +0 -156
  445. package/dist/types/mixins/OxyServices.civic.d.ts +0 -520
  446. package/dist/types/mixins/OxyServices.connectedApps.d.ts +0 -184
  447. package/dist/types/mixins/OxyServices.contacts.d.ts +0 -100
  448. package/dist/types/mixins/OxyServices.deviceBoot.d.ts +0 -185
  449. package/dist/types/mixins/OxyServices.devices.d.ts +0 -103
  450. package/dist/types/mixins/OxyServices.features.d.ts +0 -250
  451. package/dist/types/mixins/OxyServices.followGraph.d.ts +0 -223
  452. package/dist/types/mixins/OxyServices.identity.d.ts +0 -337
  453. package/dist/types/mixins/OxyServices.identityBackup.d.ts +0 -129
  454. package/dist/types/mixins/OxyServices.inference.d.ts +0 -95
  455. package/dist/types/mixins/OxyServices.language.d.ts +0 -87
  456. package/dist/types/mixins/OxyServices.linkedAccounts.d.ts +0 -107
  457. package/dist/types/mixins/OxyServices.location.d.ts +0 -70
  458. package/dist/types/mixins/OxyServices.nodes.d.ts +0 -198
  459. package/dist/types/mixins/OxyServices.notifications.d.ts +0 -143
  460. package/dist/types/mixins/OxyServices.payment.d.ts +0 -117
  461. package/dist/types/mixins/OxyServices.privacy.d.ts +0 -146
  462. package/dist/types/mixins/OxyServices.reputation.d.ts +0 -202
  463. package/dist/types/mixins/OxyServices.security.d.ts +0 -84
  464. package/dist/types/mixins/OxyServices.store.d.ts +0 -334
  465. package/dist/types/mixins/OxyServices.topics.d.ts +0 -110
  466. package/dist/types/mixins/OxyServices.user.d.ts +0 -600
  467. package/dist/types/mixins/OxyServices.utility.d.ts +0 -526
  468. package/dist/types/mixins/index.d.ts +0 -87
  469. package/dist/types/mixins/mixinHelpers.d.ts +0 -31
  470. package/dist/types/utils/webauthnOrigin.d.ts +0 -32
  471. package/src/OxyServices.base.ts +0 -480
  472. package/src/__tests__/authSocket.test.ts +0 -96
  473. package/src/__tests__/fixEsmImports.test.ts +0 -132
  474. package/src/__tests__/httpServiceAbort.test.ts +0 -308
  475. package/src/__tests__/httpServiceActivityId.test.ts +0 -49
  476. package/src/__tests__/httpServiceAuthSelfAwait.test.ts +0 -108
  477. package/src/__tests__/httpServiceCache.test.ts +0 -318
  478. package/src/__tests__/httpServiceFormEncoded.test.ts +0 -139
  479. package/src/__tests__/httpServiceQueueDeadlock.test.ts +0 -128
  480. package/src/__tests__/httpServiceRateLimitedRefresh.test.ts +0 -160
  481. package/src/__tests__/httpServiceUnwrapEnvelope.test.ts +0 -115
  482. package/src/__tests__/httpServiceWrites.test.ts +0 -175
  483. package/src/__tests__/inSessionRefresh.test.ts +0 -313
  484. package/src/__tests__/linkedClient.test.ts +0 -363
  485. package/src/__tests__/nearExpiryMintStorm.test.ts +0 -165
  486. package/src/__tests__/parseHttpErrorBody.test.ts +0 -116
  487. package/src/__tests__/publicInterfaceParity.test.ts +0 -75
  488. package/src/__tests__/serverValueImportsDeclared.test.ts +0 -120
  489. package/src/__tests__/serviceTokenWorkloadFallback.test.ts +0 -85
  490. package/src/__tests__/userIdentity.test.ts +0 -143
  491. package/src/boot/__tests__/sessionColdBoot.identity.test.ts +0 -393
  492. package/src/boot/__tests__/sessionColdBoot.sharedDevice.test.ts +0 -325
  493. package/src/boot/__tests__/sessionColdBoot.test.ts +0 -570
  494. package/src/crypto/__tests__/backupMaterial.test.ts +0 -86
  495. package/src/crypto/__tests__/cryptoPrimitives.test.ts +0 -226
  496. package/src/crypto/__tests__/identityLink.test.ts +0 -18
  497. package/src/crypto/__tests__/identityMocks.ts +0 -125
  498. package/src/crypto/__tests__/identityProof.test.ts +0 -81
  499. package/src/crypto/__tests__/keyManager.atomicity.test.ts +0 -272
  500. package/src/crypto/__tests__/keyManager.cacheSafety.test.ts +0 -175
  501. package/src/crypto/__tests__/keyManager.deviceBackup.test.ts +0 -310
  502. package/src/crypto/__tests__/keyManager.identityStatus.test.ts +0 -217
  503. package/src/crypto/__tests__/keyManager.recoveryLadder.test.ts +0 -179
  504. package/src/crypto/__tests__/keyManager.recoveryMnemonic.test.ts +0 -138
  505. package/src/crypto/__tests__/keyManager.sharedSlotSync.test.ts +0 -150
  506. package/src/crypto/__tests__/keyManager.storageMigration.test.ts +0 -227
  507. package/src/crypto/__tests__/keyManager.test.ts +0 -329
  508. package/src/crypto/__tests__/polyfill.test.ts +0 -109
  509. package/src/crypto/__tests__/polyfillOrder.test.ts +0 -114
  510. package/src/crypto/__tests__/recoveryPhrase.test.ts +0 -61
  511. package/src/crypto/__tests__/registrationPow.test.ts +0 -61
  512. package/src/crypto/__tests__/scopedSeed.test.ts +0 -126
  513. package/src/crypto/__tests__/signChallengeShared.test.ts +0 -63
  514. package/src/crypto/__tests__/signedRecord.test.ts +0 -230
  515. package/src/i18n/__tests__/accountCategoryLabels.test.ts +0 -62
  516. package/src/i18n/__tests__/accountRoleLabels.test.ts +0 -54
  517. package/src/i18n/__tests__/reputationCategoryLabels.test.ts +0 -56
  518. package/src/i18n/__tests__/trustTierLabels.test.ts +0 -47
  519. package/src/i18n/locales/de-DE.json +0 -306
  520. package/src/i18n/locales/es-ES.json +0 -2127
  521. package/src/i18n/locales/ja-JP.json +0 -306
  522. package/src/inference/__tests__/OxyInferenceClient.test.ts +0 -899
  523. package/src/logger/__tests__/logger.test.ts +0 -207
  524. package/src/mixins/OxyServices.accounts.ts +0 -1330
  525. package/src/mixins/OxyServices.agency.ts +0 -353
  526. package/src/mixins/OxyServices.analytics.ts +0 -53
  527. package/src/mixins/OxyServices.appData.ts +0 -158
  528. package/src/mixins/OxyServices.assets.ts +0 -964
  529. package/src/mixins/OxyServices.auth.ts +0 -2028
  530. package/src/mixins/OxyServices.chains.ts +0 -134
  531. package/src/mixins/OxyServices.civic.ts +0 -945
  532. package/src/mixins/OxyServices.connectedApps.ts +0 -212
  533. package/src/mixins/OxyServices.contacts.ts +0 -73
  534. package/src/mixins/OxyServices.devices.ts +0 -120
  535. package/src/mixins/OxyServices.features.ts +0 -454
  536. package/src/mixins/OxyServices.followGraph.ts +0 -293
  537. package/src/mixins/OxyServices.identity.ts +0 -787
  538. package/src/mixins/OxyServices.identityBackup.ts +0 -250
  539. package/src/mixins/OxyServices.inference.ts +0 -57
  540. package/src/mixins/OxyServices.language.ts +0 -144
  541. package/src/mixins/OxyServices.linkedAccounts.ts +0 -129
  542. package/src/mixins/OxyServices.location.ts +0 -46
  543. package/src/mixins/OxyServices.nodes.ts +0 -337
  544. package/src/mixins/OxyServices.notifications.ts +0 -142
  545. package/src/mixins/OxyServices.payment.ts +0 -163
  546. package/src/mixins/OxyServices.privacy.ts +0 -219
  547. package/src/mixins/OxyServices.reputation.ts +0 -436
  548. package/src/mixins/OxyServices.security.ts +0 -110
  549. package/src/mixins/OxyServices.store.ts +0 -585
  550. package/src/mixins/OxyServices.topics.ts +0 -169
  551. package/src/mixins/OxyServices.user.ts +0 -1208
  552. package/src/mixins/OxyServices.utility.ts +0 -1803
  553. package/src/mixins/__tests__/OxyServices.civic.test.ts +0 -1095
  554. package/src/mixins/__tests__/OxyServices.deviceBoot.test.ts +0 -124
  555. package/src/mixins/__tests__/OxyServices.identity.test.ts +0 -301
  556. package/src/mixins/__tests__/OxyServices.nodes.test.ts +0 -341
  557. package/src/mixins/__tests__/OxyServices.rotateKey.test.ts +0 -323
  558. package/src/mixins/__tests__/OxyServices.serviceAssetMetadata.test.ts +0 -192
  559. package/src/mixins/__tests__/OxyServices.serviceAssetMetadataBySha.test.ts +0 -135
  560. package/src/mixins/__tests__/OxyServices.serviceLinkedDownloadUrl.test.ts +0 -139
  561. package/src/mixins/__tests__/accountEvents.test.ts +0 -158
  562. package/src/mixins/__tests__/accounts.test.ts +0 -727
  563. package/src/mixins/__tests__/agency.test.ts +0 -120
  564. package/src/mixins/__tests__/appData.test.ts +0 -203
  565. package/src/mixins/__tests__/assetCredentials.test.ts +0 -47
  566. package/src/mixins/__tests__/assetUpload.test.ts +0 -191
  567. package/src/mixins/__tests__/authRefusalObservability.test.ts +0 -396
  568. package/src/mixins/__tests__/backgroundCredential.httpIntegration.test.ts +0 -130
  569. package/src/mixins/__tests__/chains.test.ts +0 -113
  570. package/src/mixins/__tests__/commonsSignIn.test.ts +0 -1147
  571. package/src/mixins/__tests__/connectedApps.test.ts +0 -146
  572. package/src/mixins/__tests__/deviceTokenMintPinned.test.ts +0 -113
  573. package/src/mixins/__tests__/discoveryErrorHandling.test.ts +0 -265
  574. package/src/mixins/__tests__/followCacheInvalidation.test.ts +0 -173
  575. package/src/mixins/__tests__/followGraph.test.ts +0 -147
  576. package/src/mixins/__tests__/followGraphPagination.test.ts +0 -271
  577. package/src/mixins/__tests__/getFileDownloadUrl.test.ts +0 -346
  578. package/src/mixins/__tests__/getFollowStatuses.test.ts +0 -95
  579. package/src/mixins/__tests__/getUsersByIds.test.ts +0 -176
  580. package/src/mixins/__tests__/identityBackup.test.ts +0 -315
  581. package/src/mixins/__tests__/identityLink.test.ts +0 -89
  582. package/src/mixins/__tests__/identityWriteCacheInvalidation.test.ts +0 -407
  583. package/src/mixins/__tests__/inferenceFactory.test.ts +0 -58
  584. package/src/mixins/__tests__/linkedAccounts.test.ts +0 -109
  585. package/src/mixins/__tests__/notifications.read.test.ts +0 -82
  586. package/src/mixins/__tests__/onTokensChanged.test.ts +0 -129
  587. package/src/mixins/__tests__/preSessionSkipAuth.test.ts +0 -284
  588. package/src/mixins/__tests__/privacyCacheInvalidation.test.ts +0 -155
  589. package/src/mixins/__tests__/reputation.test.ts +0 -522
  590. package/src/mixins/__tests__/serviceAuth.test.ts +0 -889
  591. package/src/mixins/__tests__/serviceTokenJwks.test.ts +0 -208
  592. package/src/mixins/__tests__/store.test.ts +0 -304
  593. package/src/mixins/__tests__/topics.test.ts +0 -155
  594. package/src/mixins/__tests__/userReadCacheBypass.test.ts +0 -129
  595. package/src/mixins/__tests__/userTokenAuth.test.ts +0 -746
  596. package/src/mixins/__tests__/verifyChallenge.test.ts +0 -161
  597. package/src/mixins/__tests__/verifyServiceActingAs.test.ts +0 -167
  598. package/src/mixins/__tests__/webauthnAuth.test.ts +0 -279
  599. package/src/mixins/index.ts +0 -203
  600. package/src/mixins/mixinHelpers.ts +0 -69
  601. package/src/server/__tests__/auth.test.ts +0 -78
  602. package/src/server/__tests__/capabilityTicket.test.ts +0 -111
  603. package/src/server/__tests__/cors.socket.test.ts +0 -225
  604. package/src/server/__tests__/cors.test.ts +0 -158
  605. package/src/server/__tests__/rateLimit.test.ts +0 -257
  606. package/src/server/__tests__/requesterAssertion.test.ts +0 -359
  607. package/src/server/__tests__/safeFetch.test.ts +0 -232
  608. package/src/server/__tests__/securityHeaders.test.ts +0 -387
  609. package/src/server/__tests__/serviceTokenAttribution.test.ts +0 -396
  610. package/src/server/__tests__/traffic.test.ts +0 -180
  611. package/src/server/__tests__/trafficNodeHttp.test.ts +0 -38
  612. package/src/server/__tests__/userInvalidation.test.ts +0 -203
  613. package/src/server/__tests__/verifySecret.test.ts +0 -40
  614. package/src/server/__tests__/workloadIdentity.client.test.ts +0 -16
  615. package/src/server/__tests__/workloadIdentity.test.ts +0 -128
  616. package/src/session/__tests__/SessionClient.additive.test.ts +0 -153
  617. package/src/session/__tests__/SessionClient.broadcastChannel.test.ts +0 -114
  618. package/src/session/__tests__/SessionClient.diagnostics.test.ts +0 -91
  619. package/src/session/__tests__/SessionClient.directory.test.ts +0 -688
  620. package/src/session/__tests__/SessionClient.httpIntegration.test.ts +0 -65
  621. package/src/session/__tests__/SessionClient.identityPin.test.ts +0 -175
  622. package/src/session/__tests__/SessionClient.rest.test.ts +0 -119
  623. package/src/session/__tests__/SessionClient.serverEvents.test.ts +0 -72
  624. package/src/session/__tests__/SessionClient.socket.test.ts +0 -202
  625. package/src/session/__tests__/SessionClient.socketFactory.test.ts +0 -81
  626. package/src/session/__tests__/SessionClient.state.test.ts +0 -78
  627. package/src/session/__tests__/SessionClient.switchTokenOrder.test.ts +0 -170
  628. package/src/session/__tests__/accountDelegationAccess.test.ts +0 -104
  629. package/src/session/__tests__/accountDialogController.test.ts +0 -2502
  630. package/src/session/__tests__/accountDialogShape.test.ts +0 -120
  631. package/src/session/__tests__/accountSwitchTargets.test.ts +0 -137
  632. package/src/session/__tests__/authStateStore.test.ts +0 -451
  633. package/src/session/__tests__/deviceDirectory.test.ts +0 -422
  634. package/src/session/__tests__/deviceSwitcherRows.test.ts +0 -223
  635. package/src/session/__tests__/identityPin.test.ts +0 -131
  636. package/src/session/__tests__/identitySession.test.ts +0 -194
  637. package/src/session/__tests__/projectSessionState.test.ts +0 -105
  638. package/src/session/__tests__/refresh.identityPin.test.ts +0 -307
  639. package/src/session/__tests__/refresh.test.ts +0 -606
  640. package/src/session/__tests__/sessionIntegration.test.ts +0 -209
  641. package/src/session/__tests__/sharedDeviceCredential.test.ts +0 -300
  642. package/src/utils/__tests__/accountUtils.test.ts +0 -151
  643. package/src/utils/__tests__/activityId.test.ts +0 -45
  644. package/src/utils/__tests__/asyncUtils.test.ts +0 -279
  645. package/src/utils/__tests__/authWebUrl.test.ts +0 -15
  646. package/src/utils/__tests__/cacheKey.test.ts +0 -0
  647. package/src/utils/__tests__/cacheLifecycle.test.ts +0 -65
  648. package/src/utils/__tests__/coldBoot.test.ts +0 -496
  649. package/src/utils/__tests__/commonsApproval.test.ts +0 -60
  650. package/src/utils/__tests__/identityCacheSweep.test.ts +0 -151
  651. package/src/utils/__tests__/languageUtils.test.ts +0 -244
  652. package/src/utils/__tests__/oauthPkce.test.ts +0 -303
  653. package/src/utils/__tests__/officialOrigins.test.ts +0 -31
  654. package/src/utils/__tests__/oxyServiceEnvironment.test.ts +0 -7
  655. package/src/utils/__tests__/profileLinks.test.ts +0 -180
  656. package/src/utils/__tests__/redactUrl.test.ts +0 -33
  657. package/src/utils/__tests__/registrableApex.test.ts +0 -62
  658. package/src/utils/__tests__/requestUtilsAbort.test.ts +0 -155
  659. package/src/utils/__tests__/textNormalization.test.ts +0 -205
  660. package/src/utils/__tests__/validationUtils.test.ts +0 -703
  661. package/src/utils/__tests__/webauthnOrigin.test.ts +0 -83
  662. package/src/utils/webauthnOrigin.ts +0 -52
@@ -1,954 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OxyServicesUserMixin = OxyServicesUserMixin;
4
- const contracts_1 = require("@oxy.so/contracts");
5
- const apiUtils_1 = require("../utils/apiUtils");
6
- const keyManager_1 = require("../crypto/keyManager");
7
- const signatureService_1 = require("../crypto/signatureService");
8
- const userIdentity_1 = require("../utils/userIdentity");
9
- const identityCacheSweep_1 = require("../utils/identityCacheSweep");
10
- const accountCacheSweep_1 = require("../utils/accountCacheSweep");
11
- const logger_1 = require("../logger");
12
- const errorUtils_1 = require("../utils/errorUtils");
13
- /**
14
- * Maximum number of ids sent per `POST /users/by-ids` request. Matches the
15
- * server-side batch cap; larger inputs are split into multiple chunked calls.
16
- */
17
- const USERS_BY_IDS_CHUNK_SIZE = 100;
18
- /**
19
- * Maximum number of ids sent per `POST /users/follow-status/bulk` request.
20
- * Matches the server-side `MAX_BULK_FOLLOW` cap; larger inputs are split into
21
- * multiple chunked calls whose result maps are merged.
22
- */
23
- const FOLLOW_STATUS_CHUNK_SIZE = 200;
24
- function OxyServicesUserMixin(Base) {
25
- return class extends Base {
26
- constructor(...args) {
27
- super(...args);
28
- }
29
- /**
30
- * Get profile by username.
31
- *
32
- * @param username - The profile's username.
33
- * @param options.cache - Defaults to `true` (5-minute TTL), matching prior
34
- * behavior. Pass `{ cache: false }` to force a registry-fresh read: the
35
- * request bypasses BOTH the cache lookup and the post-fetch cache write
36
- * (see {@link HttpService.request}'s `cache` handling), so it neither
37
- * serves nor overwrites any entry already cached for this key — a
38
- * previously cached response (if one exists) is left in place until its
39
- * own TTL expires or is explicitly invalidated elsewhere. Use this when a
40
- * caller must observe a just-written change (e.g. a privacy/consent flag)
41
- * that would otherwise be masked by the TTL window.
42
- */
43
- async getProfileByUsername(username, options) {
44
- try {
45
- const user = await this.makeRequest('GET', `/profiles/username/${encodeURIComponent(username)}`, undefined, {
46
- cache: options?.cache ?? true,
47
- cacheTTL: 5 * 60 * 1000, // 5 minutes cache for profiles
48
- });
49
- return (0, userIdentity_1.normalizeUserIdentity)(user);
50
- }
51
- catch (error) {
52
- throw this.handleError(error);
53
- }
54
- }
55
- /**
56
- * Lightweight username lookup for login flows.
57
- * Returns minimal public info: exists, color, avatar, name.displayName.
58
- * Faster than getProfileByUsername — no stats, no formatting.
59
- */
60
- async lookupUsername(username) {
61
- return await this.makeRequest('GET', `/auth/lookup/${encodeURIComponent(username)}`, undefined, {
62
- cache: true,
63
- cacheTTL: 60 * 1000, // 1 minute cache
64
- // Public login-flow lookup (pre-session) — skip the bearer preflight.
65
- skipAuth: true,
66
- });
67
- }
68
- /**
69
- * Search user profiles
70
- *
71
- * Takes an `AbortSignal` because people search is typed into: without one
72
- * every keystroke started a search that ran to completion and had its
73
- * result discarded, while holding one of the request queue's slots. It was
74
- * the only search lane in Mention that could not be cancelled, purely
75
- * because this signature had no way to say so.
76
- */
77
- async searchProfiles(query, pagination, options) {
78
- try {
79
- const response = await this.makeRequest('GET', '/profiles/search', (0, apiUtils_1.buildQueryParams)({ query, ...pagination }), {
80
- cache: true,
81
- cacheTTL: 2 * 60 * 1000, // 2 minutes cache
82
- signal: options?.signal,
83
- });
84
- if (typeof response !== 'object' ||
85
- response === null ||
86
- !Array.isArray(response.data)) {
87
- throw new Error('Unexpected search response format');
88
- }
89
- const paginationInfo = response.pagination ?? {
90
- total: response.data.length,
91
- limit: pagination?.limit ?? response.data.length,
92
- offset: pagination?.offset ?? 0,
93
- hasMore: response.data.length === (pagination?.limit ?? response.data.length) &&
94
- (pagination?.limit ?? response.data.length) > 0,
95
- };
96
- return {
97
- data: response.data,
98
- pagination: paginationInfo,
99
- };
100
- }
101
- catch (error) {
102
- throw this.handleError(error);
103
- }
104
- }
105
- /**
106
- * Resolve a fediverse handle to an Oxy user profile.
107
- * Performs WebFinger discovery and returns the user, or null if not found.
108
- * @param handle - Fediverse handle (e.g. "@user@mastodon.social" or "user@domain")
109
- */
110
- async resolveProfile(handle) {
111
- try {
112
- const result = await this.makeRequest('GET', '/profiles/resolve', {
113
- handle,
114
- }, {
115
- cache: true,
116
- // 5 min — matches the sibling profile fetches (getUserById /
117
- // getProfileByUsername). /profiles/resolve now carries the viewer-relative
118
- // `relationship` (isFollowing / followsYou); `followsYou` is target→viewer,
119
- // so the viewer can't self-refresh it via a follow action. The GET cache is
120
- // identity-scoped (keyed by the caller's access-token identity tag → no
121
- // cross-viewer poison), so a short TTL keeps "Follows you" reasonably fresh
122
- // without a per-call bypass. The identity fields alone tolerate a longer
123
- // window, but a 24h stale relationship is not acceptable.
124
- cacheTTL: 5 * 60 * 1000,
125
- });
126
- return (0, userIdentity_1.normalizeUserIdentityOrNull)(result);
127
- }
128
- catch (error) {
129
- // Discovery is best-effort: an unresolvable handle is a normal "not
130
- // found", not an exceptional condition, so the contract stays `null`.
131
- // But a 404 (handle genuinely absent) must be distinguishable from a
132
- // network/server failure (WebFinger upstream down, 5xx) for debugging —
133
- // both used to be swallowed identically. Log at `debug` with context so
134
- // the distinction is observable without turning expected misses into
135
- // noise. Return contract is unchanged.
136
- const status = (0, errorUtils_1.extractErrorStatus)(error);
137
- const isNotFound = status === 404;
138
- logger_1.logger.debug(isNotFound ? 'resolveProfile: handle not found' : 'resolveProfile: discovery failed', {
139
- method: 'resolveProfile',
140
- handle,
141
- status,
142
- notFound: isNotFound,
143
- error: error instanceof Error ? error.message : String(error),
144
- });
145
- return null;
146
- }
147
- }
148
- /**
149
- * Resolve (find or create) a non-local user. All user creation for
150
- * external accounts (federated, agent, automated) goes through this
151
- * method — calling services never write user data directly.
152
- */
153
- async resolveExternalUser(data) {
154
- return (0, userIdentity_1.normalizeUserIdentity)(await this.makeRequest('PUT', '/users/resolve', data));
155
- }
156
- /**
157
- * Get profile recommendations.
158
- *
159
- * Public discovery read — works WITHOUT authentication. The SDK attaches the
160
- * access token automatically when one is available (personalized via
161
- * mutual-connection overlap), and falls back to popular public profiles when
162
- * the caller is logged out. This deliberately does NOT use `withAuthRetry`,
163
- * which would throw an authentication timeout for logged-out callers before
164
- * the request is ever sent.
165
- *
166
- * Routing (two server endpoints, both validated against the same
167
- * `@oxy.so/contracts` recommendation schemas so the wire shape cannot drift):
168
- *
169
- * - **GET `/profiles/recommendations`** (cached) is used for the simple,
170
- * back-compatible case: no options at all, or only `excludeTypes` and/or
171
- * `limit`. `excludeTypes` is sent as a comma-joined query param and
172
- * `limit` as a numeric query param — byte-for-byte identical to the legacy
173
- * behavior so every existing caller keeps the same request and cache key.
174
- * - **POST `/profiles/recommendations`** is used whenever any of the scored
175
- * (v2) fields — `boosts`, `excludeIds`, `signalWeights`, `clientId`, or
176
- * `offset` — is present. The full options object is validated with
177
- * `recommendationRequestSchema` and sent as the request body. The POST is
178
- * cached by the HttpService keyed on the serialized body, so repeated
179
- * identical scored requests are deduplicated/cached just like the GET path.
180
- *
181
- * @param options - {@link RecommendationRequest} from `@oxy.so/contracts`.
182
- * Omitted entirely (or `{ excludeTypes }`) preserves the legacy GET path.
183
- */
184
- async getProfileRecommendations(options) {
185
- // The scored (v2) POST path is selected when any field beyond the
186
- // legacy GET-supported `excludeTypes`/`limit` pair is present.
187
- const usesScoredPath = Boolean(options &&
188
- (options.clientId !== undefined ||
189
- options.offset !== undefined ||
190
- (options.excludeIds?.length ?? 0) > 0 ||
191
- (options.boosts?.length ?? 0) > 0 ||
192
- options.signalWeights !== undefined));
193
- try {
194
- if (usesScoredPath && options) {
195
- // Validate the full request against the shared contract before
196
- // sending. A malformed payload is surfaced to the caller rather than
197
- // bounced by the server, and the parsed value strips unknown keys.
198
- const body = contracts_1.recommendationRequestSchema.parse(options);
199
- return await this.makeRequest('POST', '/profiles/recommendations', body,
200
- // Cache keyed on the serialized body (see HttpService.generateCacheKey)
201
- // so identical scored requests are served from cache, matching the
202
- // GET path's caching semantics.
203
- { cache: true });
204
- }
205
- const params = {};
206
- if (options?.excludeTypes?.length) {
207
- params.excludeTypes = options.excludeTypes.join(',');
208
- }
209
- if (options?.limit !== undefined) {
210
- params.limit = String(options.limit);
211
- }
212
- return await this.makeRequest('GET', '/profiles/recommendations', Object.keys(params).length > 0 ? params : undefined, { cache: true });
213
- }
214
- catch (error) {
215
- // Recommendations are a discovery read; failures are surfaced to the
216
- // caller (contract unchanged: rethrow via `handleError`). Add debug
217
- // observability first so a recurring upstream failure is diagnosable
218
- // — distinguishing an auth/transport problem from a server 5xx.
219
- logger_1.logger.debug('getProfileRecommendations: discovery read failed', {
220
- method: 'getProfileRecommendations',
221
- path: usesScoredPath ? 'POST' : 'GET',
222
- excludeTypes: options?.excludeTypes,
223
- status: (0, errorUtils_1.extractErrorStatus)(error),
224
- error: error instanceof Error ? error.message : String(error),
225
- });
226
- throw this.handleError(error);
227
- }
228
- }
229
- /**
230
- * Get profiles similar to a given user, based on co-follower overlap.
231
- */
232
- async getSimilarProfiles(userId, limitOrParams) {
233
- const pagination = typeof limitOrParams === 'number' ? { limit: limitOrParams } : limitOrParams ?? {};
234
- const params = (0, apiUtils_1.buildQueryParams)(pagination);
235
- const users = await this.makeRequest('GET', `/profiles/${userId}/similar`, params, {
236
- cache: true,
237
- cacheTTL: 5 * 60 * 1000, // 5 min cache
238
- });
239
- return users.map((user) => (0, userIdentity_1.normalizeUserIdentity)(user));
240
- }
241
- /**
242
- * Get user by ID.
243
- *
244
- * @param userId - The target user's id.
245
- * @param options.cache - Defaults to `true` (5-minute TTL), matching prior
246
- * behavior. Pass `{ cache: false }` to force a registry-fresh read: the
247
- * request bypasses BOTH the cache lookup and the post-fetch cache write
248
- * (see {@link HttpService.request}'s `cache` handling), so it neither
249
- * serves nor overwrites any entry already cached for this key — a
250
- * previously cached response (if one exists) is left in place until its
251
- * own TTL expires or is explicitly invalidated elsewhere. Use this when a
252
- * caller must observe a just-written change (e.g. a privacy/consent flag)
253
- * that would otherwise be masked by the TTL window.
254
- */
255
- async getUserById(userId, options) {
256
- try {
257
- const user = await this.makeRequest('GET', `/users/${userId}`, undefined, {
258
- cache: options?.cache ?? true,
259
- cacheTTL: 5 * 60 * 1000, // 5 minutes cache
260
- });
261
- return (0, userIdentity_1.normalizeUserIdentity)(user);
262
- }
263
- catch (error) {
264
- throw this.handleError(error);
265
- }
266
- }
267
- /**
268
- * Fetch many users by id in one round-trip per chunk.
269
- *
270
- * Built for feed/hydration call sites that would otherwise issue one
271
- * `getUserById` request per unique author (the classic M+1). Ids are
272
- * deduplicated and validated (empty/blank ids dropped) before being split
273
- * into chunks of {@link USERS_BY_IDS_CHUNK_SIZE} and POSTed to
274
- * `/users/by-ids` as `{ ids }`. The server returns the matched users as a
275
- * flat `User[]` (order is not guaranteed and the caller is expected to map
276
- * by `id`); each is run through `normalizeUserIdentity`, matching
277
- * `getUserById`.
278
- *
279
- * **Dual-mode auth.** `/users/by-ids` is `optionalUserOrServiceAuth` on
280
- * oxy-api: it accepts a service token, a user session, or an anonymous
281
- * caller, and returns the SAME public `{ data: PublicUserProfile[] }`
282
- * payload (canonical `name.displayName` + `_count`) in every case — no
283
- * viewer-specific fields. This method picks the path automatically:
284
- * - **Service host (backend):** when `configureServiceAuth(apiKey,
285
- * apiSecret)` has been called, OR the process can attest its workload
286
- * identity (ADR 0026 — an ECS task with no key pair), the chunk is fetched
287
- * via `makeServiceRequest`
288
- * (attaches `Authorization: Bearer <serviceToken>`). This is the
289
- * server-to-server feed/notification hydration path (e.g. Mention's
290
- * `PostHydrationService`) and is unchanged.
291
- * - **Plain client (browser / React Native with a user session):** when no
292
- * service credentials are configured, the chunk is fetched via
293
- * `makeRequest`, which attaches the configured user bearer. Previously
294
- * this method always used the service path, so every client-side caller
295
- * silently received `[]` because `getServiceToken()` had no credentials.
296
- *
297
- * Both paths run results through `normalizeUserIdentity` and unwrap the
298
- * API's `{ data }` envelope identically (`makeServiceRequest` is literally
299
- * `makeRequest` plus a bearer service header).
300
- *
301
- * Resilience: chunks are independent. A failed chunk is logged and skipped
302
- * — the method returns every user that resolved successfully rather than
303
- * discarding the whole call on one chunk's failure. An empty/whitespace-only
304
- * input resolves immediately with `[]` and performs no network call.
305
- *
306
- * Not cached at the SDK layer: the response is keyed on a multi-id POST body
307
- * (low hit rate) and the backend maintains its own per-id Redis cache.
308
- */
309
- async getUsersByIds(ids) {
310
- const uniqueIds = Array.from(new Set(ids.filter((id) => typeof id === 'string' && id.trim().length > 0)));
311
- if (uniqueIds.length === 0) {
312
- return [];
313
- }
314
- const chunks = [];
315
- for (let i = 0; i < uniqueIds.length; i += USERS_BY_IDS_CHUNK_SIZE) {
316
- chunks.push(uniqueIds.slice(i, i + USERS_BY_IDS_CHUNK_SIZE));
317
- }
318
- // A backend uses the bearer-service path; any other caller (browser / RN
319
- // with a user session) uses the user-bearer path. "A backend" means one
320
- // that can get a service token at all — a key pair, OR a task role it can
321
- // attest. Asking only about the key pair sent every attested backend down
322
- // the user path with no bearer: an anonymous request, charged to the
323
- // shared NAT address's per-IP budget and slowed by its 500ms penalty.
324
- // Measured from Mention's task (2026-09-25): 520ms per anonymous chunk
325
- // against 20ms with the service token, enough to put its 1.5s hydration
326
- // deadline out of reach on every cache miss.
327
- const useServiceAuth = Boolean(this._serviceApiKey && this._serviceApiSecret)
328
- || await this._canUseWorkloadIdentity();
329
- // Run chunks concurrently; a single chunk failure must not sink the rest.
330
- const settled = await Promise.all(chunks.map(async (chunk) => {
331
- try {
332
- const users = useServiceAuth
333
- ? await this.makeServiceRequest('POST', '/users/by-ids', { ids: chunk })
334
- : await this.makeRequest('POST', '/users/by-ids', { ids: chunk }, { cache: false });
335
- return Array.isArray(users) ? users.map((user) => (0, userIdentity_1.normalizeUserIdentity)(user)) : [];
336
- }
337
- catch (error) {
338
- logger_1.logger.warn('getUsersByIds: chunk failed, continuing with remaining chunks', {
339
- method: 'getUsersByIds',
340
- mode: useServiceAuth ? 'service' : 'user',
341
- chunkSize: chunk.length,
342
- status: (0, errorUtils_1.extractErrorStatus)(error),
343
- error: error instanceof Error ? error.message : String(error),
344
- });
345
- return [];
346
- }
347
- }));
348
- return settled.flat();
349
- }
350
- /**
351
- * Get current user
352
- */
353
- async getCurrentUser() {
354
- return this.withAuthRetry(async () => {
355
- const user = await this.makeRequest('GET', '/users/me', undefined, {
356
- cache: true,
357
- cacheTTL: 1 * 60 * 1000, // 1 minute cache for current user
358
- });
359
- return (0, userIdentity_1.normalizeUserIdentity)(user);
360
- }, 'getCurrentUser');
361
- }
362
- /**
363
- * Update user profile.
364
- *
365
- * Invalidates the SDK-side response cache for every endpoint that can
366
- * return this user — the list is owned by {@link evictOxyIdentityCache}, so
367
- * a new identity read is added in one place instead of to each writer
368
- * separately (this method's own hand-written copy had already drifted from
369
- * the server-side one, missing `GET /auth/lookup/*` and
370
- * `GET /profiles/resolve`). The account forest (`GET /accounts` and the
371
- * caller's own detail row) is swept too — a personal account IS this user,
372
- * and `AccountNode.account` embeds the whole profile — from the list that
373
- * {@link evictOxyAccountForestCache} owns, for the same reason: the accounts
374
- * mixin writes those keys as well, and two hand-written copies drift.
375
- *
376
- * TanStack Query handles offline queuing automatically.
377
- */
378
- async updateProfile(updates) {
379
- try {
380
- const result = (0, userIdentity_1.normalizeUserIdentity)(await this.makeRequest('PUT', '/users/me', updates, { cache: false }));
381
- (0, identityCacheSweep_1.evictOxyIdentityCache)(this, result?.id);
382
- (0, accountCacheSweep_1.evictOxyAccountForestCache)(this, result?.id);
383
- return result;
384
- }
385
- catch (error) {
386
- const errorMessage = error instanceof Error ? error.message : String(error);
387
- const status = (0, errorUtils_1.extractErrorStatus)(error);
388
- // Check if it's an authentication error (401)
389
- const isAuthError = status === 401 ||
390
- errorMessage.includes('Authentication required') ||
391
- errorMessage.includes('Invalid or missing authorization header');
392
- // If authentication error and we don't have a token, this might be an offline session
393
- // The caller should handle syncing the session before retrying
394
- if (isAuthError && !this.hasValidToken()) {
395
- // Re-throw with a specific message so the caller knows to sync
396
- throw new Error('AUTH_REQUIRED_OFFLINE_SESSION: Session needs to be synced to get a token');
397
- }
398
- throw this.handleError(error);
399
- }
400
- }
401
- /**
402
- * Get privacy settings for a user
403
- * @param userId - The user ID (defaults to current user)
404
- */
405
- async getPrivacySettings(userId) {
406
- try {
407
- const id = userId || (await this.getCurrentUser()).id;
408
- return await this.makeRequest('GET', `/privacy/${id}/privacy`, undefined, {
409
- cache: true,
410
- cacheTTL: 2 * 60 * 1000, // 2 minutes cache
411
- });
412
- }
413
- catch (error) {
414
- throw this.handleError(error);
415
- }
416
- }
417
- /**
418
- * Update privacy settings.
419
- *
420
- * Invalidates the cached `GET /privacy/<id>/privacy` response (the exact
421
- * key `getPrivacySettings` reads, scoped to the same `id`) after the write.
422
- * `getPrivacySettings` caches for ~2 minutes (identity-scoped); without
423
- * busting that entry, a follow-up read within the TTL window returns the
424
- * pre-update settings. `clearCacheEntry` deletes every identity-scoped
425
- * variant of the key.
426
- * @param settings - Partial privacy settings object
427
- * @param userId - The user ID (defaults to current user)
428
- */
429
- async updatePrivacySettings(settings, userId) {
430
- try {
431
- const id = userId || (await this.getCurrentUser()).id;
432
- const result = await this.makeRequest('PATCH', `/privacy/${id}/privacy`, settings, {
433
- cache: false,
434
- });
435
- // Privacy settings ride the user DTO, so every identity read goes stale
436
- // too — same key list as any other profile write.
437
- (0, identityCacheSweep_1.evictOxyIdentityCache)(this, id);
438
- this.clearCacheEntry(`GET:/privacy/${id}/privacy`);
439
- return result;
440
- }
441
- catch (error) {
442
- throw this.handleError(error);
443
- }
444
- }
445
- /**
446
- * Update the authenticated user's notification preferences.
447
- *
448
- * Thin wrapper over `updateProfile` that constrains the patch to known
449
- * notification channels — same persistence path, same cache invalidation,
450
- * but type-safe at the call site.
451
- */
452
- async updateNotificationPreferences(preferences) {
453
- return this.updateProfile({ notificationPreferences: preferences });
454
- }
455
- /**
456
- * Update the authenticated user's general preferences (language, theme,
457
- * reduce-motion, timezone). Persisted on the User document via
458
- * `PUT /users/me` — same cache-invalidation behaviour as `updateProfile`.
459
- */
460
- async updateUserPreferences(preferences) {
461
- return this.updateProfile({ userPreferences: preferences });
462
- }
463
- /**
464
- * Update the authenticated user's portable theme preference (light/dark/
465
- * system + Bloom color-preset key). Persisted on the User document via the
466
- * SAME `PUT /users/me` settings path as the other preferences — same cache
467
- * invalidation — so the next cold boot serves it on the self/session payload
468
- * with no extra network call. The full object is written (both `mode` and
469
- * `colorPreset` are required by the API).
470
- */
471
- async updateThemePreference(themePreference) {
472
- return this.updateProfile({ themePreference });
473
- }
474
- /**
475
- * Request account verification
476
- */
477
- async requestAccountVerification(reason, evidence) {
478
- try {
479
- return await this.makeRequest('POST', '/users/verify/request', {
480
- reason,
481
- evidence,
482
- }, { cache: false });
483
- }
484
- catch (error) {
485
- throw this.handleError(error);
486
- }
487
- }
488
- /**
489
- * Download account data export
490
- */
491
- async downloadAccountData(format = 'json') {
492
- try {
493
- // Use httpService for blob responses (it handles blob responses automatically)
494
- const result = await this.getClient().request({
495
- method: 'GET',
496
- url: `/users/me/data`,
497
- params: { format },
498
- cache: false,
499
- responseType: 'blob',
500
- });
501
- return result;
502
- }
503
- catch (error) {
504
- throw this.handleError(error);
505
- }
506
- }
507
- /**
508
- * Delete account permanently.
509
- *
510
- * Signs `delete:{publicKey}:{timestamp}` with the locally-stored identity
511
- * private key and submits the signature alongside the confirmation text
512
- * (must equal the user's username). The signature is the cryptographic
513
- * proof of ownership — only the device holding the private key can issue
514
- * a valid signature, so no password is required.
515
- *
516
- * @param confirmText - Must equal the user's username (verified server-side)
517
- * @throws If no identity is stored on this device, or signing fails
518
- */
519
- async deleteAccount(confirmText) {
520
- try {
521
- const publicKey = await keyManager_1.KeyManager.getPublicKey();
522
- if (!publicKey) {
523
- throw new Error('No identity found on this device. Account deletion requires the device that holds your identity key.');
524
- }
525
- const timestamp = Date.now();
526
- const message = `delete:${publicKey}:${timestamp}`;
527
- const signature = await signatureService_1.SignatureService.sign(message);
528
- return await this.makeRequest('DELETE', '/users/me', {
529
- signature,
530
- timestamp,
531
- confirmText,
532
- }, { cache: false });
533
- }
534
- catch (error) {
535
- throw this.handleError(error);
536
- }
537
- }
538
- /**
539
- * WebAuthn request options to delete a PASSKEY account (ADR 0029 D3): its own
540
- * passkeys, user verification required, and a challenge bound to it. Opaque —
541
- * hand them to the browser's authentication ceremony, on auth.oxy.so. An
542
- * account with a Commons key deletes with {@link deleteAccount} instead.
543
- */
544
- async getAccountDeletionOptions() {
545
- try {
546
- return await this.makeRequest('POST', '/users/me/delete/options', undefined, { cache: false });
547
- }
548
- catch (error) {
549
- throw this.handleError(error);
550
- }
551
- }
552
- /**
553
- * Delete a PASSKEY account permanently, with an assertion by one of its
554
- * passkeys over {@link getAccountDeletionOptions}' challenge.
555
- *
556
- * @param confirmText - Must equal the user's username (verified server-side)
557
- * @param assertion - The ceremony's opaque `AuthenticationResponseJSON`
558
- */
559
- async deleteAccountWithPasskey(confirmText, assertion) {
560
- try {
561
- return await this.makeRequest('DELETE', '/users/me', { confirmText, assertion }, { cache: false });
562
- }
563
- catch (error) {
564
- throw this.handleError(error);
565
- }
566
- }
567
- /**
568
- * Invalidate every cached read a follow/unfollow write invalidates.
569
- *
570
- * Shared by the four mutation entry points (`followUser`, `unfollowUser`,
571
- * `followUsers`, `unfollowUsers`) so they can never drift on which caches a
572
- * write busts.
573
- *
574
- * The follower/following/mutuals LISTS are cleared by PREFIX rather than by
575
- * exact key. Those reads are paginated and ordered, so one logical list is
576
- * spread across many content-addressed keys
577
- * (`GET:/users/<id>/followers:{"limit":"20","offset":"40","sort":"oldest"}`);
578
- * an exact-key clear would only bust whichever page/sort variant happened to
579
- * be read last and would leave every other page stale. `clearCacheByPrefix`
580
- * deletes all of them, and all identity-scoped variants of each.
581
- */
582
- invalidateFollowGraphCaches(targetUserIds) {
583
- for (const id of targetUserIds) {
584
- this.clearCacheEntry(`GET:/users/${id}/follow-status`);
585
- // Profile fetches embed viewer-relative `relationship` — bust so a
586
- // remount doesn't serve a stale isFollowing for up to 5 minutes.
587
- this.clearCacheEntry(`GET:/users/${id}`);
588
- // The target gained/lost a follower, and the viewer's presence in the
589
- // target's "followers you know" set changed with it.
590
- this.clearCacheByPrefix(`GET:/users/${id}/followers`);
591
- this.clearCacheByPrefix(`GET:/users/${id}/mutuals`);
592
- }
593
- this.clearCacheByPrefix('GET:/profiles/username/');
594
- this.clearCacheByPrefix('GET:/profiles/resolve');
595
- // The write changed the viewer's OWN following list and graph.
596
- const viewerId = this.getCurrentUserId();
597
- if (viewerId) {
598
- this.clearCacheByPrefix(`GET:/users/${viewerId}/following`);
599
- }
600
- this.clearCacheEntry('GET:/users/me/graph');
601
- }
602
- /**
603
- * Follow a user.
604
- *
605
- * Invalidates the cached `GET /users/<id>/follow-status` response after
606
- * the write. `getFollowStatus` caches for ~1 minute (identity-scoped);
607
- * without busting that entry, a `FollowButton` that remounts within the
608
- * TTL window re-reads the STALE pre-write status and reverts the optimistic
609
- * UI (the "follow resets after navigating away and back" bug).
610
- * `clearCacheEntry` deletes every identity-scoped variant of the key.
611
- */
612
- async followUser(userId) {
613
- try {
614
- const result = await this.makeRequest('POST', `/users/${userId}/follow`, undefined, { cache: false });
615
- this.invalidateFollowGraphCaches([userId]);
616
- return result;
617
- }
618
- catch (error) {
619
- throw this.handleError(error);
620
- }
621
- }
622
- /**
623
- * Follow multiple users in a single request.
624
- *
625
- * POSTs `/users/follow/bulk` with `{ userIds }` (server caps the batch at
626
- * 200). Returns the per-user outcomes and the count of users newly
627
- * followed. An empty `userIds` array resolves immediately with an empty
628
- * result and performs no network call.
629
- */
630
- async followUsers(userIds) {
631
- if (userIds.length === 0) {
632
- return { results: [], followedCount: 0 };
633
- }
634
- try {
635
- const result = await this.makeRequest('POST', '/users/follow/bulk', { userIds }, { cache: false });
636
- this.invalidateFollowGraphCaches(userIds);
637
- return result;
638
- }
639
- catch (error) {
640
- throw this.handleError(error);
641
- }
642
- }
643
- /**
644
- * Unfollow multiple users in a single request.
645
- *
646
- * POSTs `/users/unfollow/bulk` with `{ userIds }` (server caps the batch at
647
- * 200). Returns the per-user outcomes and the count of users newly
648
- * unfollowed. An empty `userIds` array resolves immediately with an empty
649
- * result and performs no network call.
650
- */
651
- async unfollowUsers(userIds) {
652
- if (userIds.length === 0) {
653
- return { results: [], unfollowedCount: 0 };
654
- }
655
- try {
656
- const result = await this.makeRequest('POST', '/users/unfollow/bulk', { userIds }, { cache: false });
657
- this.invalidateFollowGraphCaches(userIds);
658
- return result;
659
- }
660
- catch (error) {
661
- throw this.handleError(error);
662
- }
663
- }
664
- /**
665
- * Unfollow a user
666
- */
667
- async unfollowUser(userId) {
668
- try {
669
- const result = await this.makeRequest('DELETE', `/users/${userId}/follow`, undefined, { cache: false });
670
- this.invalidateFollowGraphCaches([userId]);
671
- return result;
672
- }
673
- catch (error) {
674
- throw this.handleError(error);
675
- }
676
- }
677
- /**
678
- * Get follow status
679
- */
680
- async getFollowStatus(userId) {
681
- try {
682
- return await this.makeRequest('GET', `/users/${userId}/follow-status`, undefined, {
683
- cache: true,
684
- cacheTTL: 1 * 60 * 1000, // 1 minute cache
685
- });
686
- }
687
- catch (error) {
688
- throw this.handleError(error);
689
- }
690
- }
691
- /**
692
- * Resolve the viewer's follow status for MANY users in one round-trip per
693
- * chunk. Built for list UIs (a page of `FollowButton`s) that would otherwise
694
- * fire one `getFollowStatus` per button (the classic N+1).
695
- *
696
- * Ids are deduplicated and validated (empty/blank ids dropped), split into
697
- * chunks of {@link FOLLOW_STATUS_CHUNK_SIZE} (the server's bulk cap), and
698
- * POSTed to `/users/follow-status/bulk` as `{ userIds }`. The per-chunk
699
- * `{ statuses }` maps are merged into one `Record<string, boolean>` covering
700
- * every requested id — ids the viewer does not follow come back `false`.
701
- *
702
- * Uncached (`{ cache: false }`): the UI store owns follow-status freshness
703
- * and writes optimistically on every mutation, so an SDK cache here would
704
- * serve a stale status right after a follow/unfollow. An empty/whitespace-
705
- * only input resolves immediately with `{}` and performs no network call.
706
- */
707
- async getFollowStatuses(userIds) {
708
- const uniqueIds = Array.from(new Set(userIds.filter((id) => typeof id === 'string' && id.trim().length > 0)));
709
- if (uniqueIds.length === 0) {
710
- return {};
711
- }
712
- const chunks = [];
713
- for (let i = 0; i < uniqueIds.length; i += FOLLOW_STATUS_CHUNK_SIZE) {
714
- chunks.push(uniqueIds.slice(i, i + FOLLOW_STATUS_CHUNK_SIZE));
715
- }
716
- try {
717
- const responses = await Promise.all(chunks.map((chunk) => this.makeRequest('POST', '/users/follow-status/bulk', { userIds: chunk }, { cache: false })));
718
- const merged = {};
719
- for (const response of responses) {
720
- Object.assign(merged, response?.statuses ?? {});
721
- }
722
- return merged;
723
- }
724
- catch (error) {
725
- throw this.handleError(error);
726
- }
727
- }
728
- /**
729
- * Get user followers.
730
- *
731
- * `sort` orders the underlying follow edges — `recent` (newest first, the
732
- * server default) or `oldest`. Because the response is cached and the cache
733
- * key is content-addressed on the query params, each `limit`/`offset`/`sort`
734
- * combination is its own entry.
735
- */
736
- async getUserFollowers(userId, pagination) {
737
- try {
738
- const params = (0, apiUtils_1.buildQueryParams)(pagination || {});
739
- const response = await this.makeRequest('GET', `/users/${userId}/followers`, params, {
740
- cache: true,
741
- cacheTTL: 2 * 60 * 1000, // 2 minutes cache
742
- });
743
- return {
744
- followers: response.data || [],
745
- total: response.pagination.total,
746
- hasMore: response.pagination.hasMore,
747
- };
748
- }
749
- catch (error) {
750
- throw this.handleError(error);
751
- }
752
- }
753
- /**
754
- * Get user following. `sort` behaves as in {@link getUserFollowers}.
755
- */
756
- async getUserFollowing(userId, pagination) {
757
- try {
758
- const params = (0, apiUtils_1.buildQueryParams)(pagination || {});
759
- const response = await this.makeRequest('GET', `/users/${userId}/following`, params, {
760
- cache: true,
761
- cacheTTL: 2 * 60 * 1000, // 2 minutes cache
762
- });
763
- return {
764
- following: response.data || [],
765
- total: response.pagination.total,
766
- hasMore: response.pagination.hasMore,
767
- };
768
- }
769
- catch (error) {
770
- throw this.handleError(error);
771
- }
772
- }
773
- /**
774
- * Get user mutuals ("followers you know" — users the authenticated viewer
775
- * follows who also follow `userId`). The viewer is derived server-side from auth.
776
- */
777
- async getUserMutuals(userId, pagination) {
778
- try {
779
- const params = (0, apiUtils_1.buildQueryParams)(pagination || {});
780
- const response = await this.makeRequest('GET', `/users/${userId}/mutuals`, params, {
781
- cache: true,
782
- cacheTTL: 2 * 60 * 1000, // 2 minutes cache
783
- });
784
- return {
785
- mutuals: response.data || [],
786
- total: response.pagination.total,
787
- hasMore: response.pagination.hasMore,
788
- };
789
- }
790
- catch (error) {
791
- throw this.handleError(error);
792
- }
793
- }
794
- /**
795
- * Get the authenticated VIEWER's OWN mutual-follow user ids — the accounts the
796
- * viewer follows that ALSO follow the viewer back (a bidirectional follow
797
- * edge). The viewer is derived server-side from the SDK's auth token (never a
798
- * param), so there is no target id to pass.
799
- *
800
- * Returns a bounded, lean list of ids meant to SEED a "Mutuals" feed (the
801
- * consumer hydrates/ranks the posts itself) — distinct from
802
- * {@link getUserMutuals}, which returns hydrated "followers you know" DTOs
803
- * about ANOTHER profile. An anonymous caller resolves to an empty array.
804
- */
805
- async getMutualUserIds(params) {
806
- try {
807
- const query = (0, apiUtils_1.buildPaginationParams)(params || {});
808
- const response = await this.makeRequest('GET', '/users/mutual-ids', query, {
809
- cache: true,
810
- cacheTTL: 2 * 60 * 1000, // 2 minutes cache
811
- });
812
- return response.data || [];
813
- }
814
- catch (error) {
815
- throw this.handleError(error);
816
- }
817
- }
818
- /**
819
- * Get the authenticated VIEWER's bounded "follows-of-follows" user ids — the
820
- * union of the accounts followed by the accounts the viewer follows (a
821
- * two-hop walk of the follow graph), MINUS the viewer's own follows and the
822
- * viewer themselves. The viewer is derived server-side from the SDK's auth
823
- * token (never a param), so there is no target id to pass.
824
- *
825
- * Returns a bounded, lean list of ids meant to SEED a friends-of-friends
826
- * feed (the consumer hydrates/ranks the posts itself), ordered by frequency
827
- * (accounts followed by more of the viewer's follows first), then recency.
828
- * An anonymous caller resolves to an empty array. Mirrors
829
- * {@link getMutualUserIds}'s caching posture.
830
- */
831
- async getFollowsOfFollowsIds(params) {
832
- try {
833
- const query = (0, apiUtils_1.buildPaginationParams)(params || {});
834
- const response = await this.makeRequest('GET', '/users/follows-of-follows-ids', query, {
835
- cache: true,
836
- cacheTTL: 2 * 60 * 1000, // 2 minutes cache
837
- });
838
- return response.data || [];
839
- }
840
- catch (error) {
841
- throw this.handleError(error);
842
- }
843
- }
844
- /**
845
- * Get the authenticated VIEWER's OWN social graph — the accounts they follow,
846
- * the subset who follow back (mutuals), and the accounts they have blocked —
847
- * as ONE ids-only payload. The viewer is derived server-side from the SDK's
848
- * auth token (never a param).
849
- *
850
- * Consolidates what were three separate round trips (`getUserFollowing` /
851
- * `getMutualUserIds` / `getBlockedUsers`) into a single request so a consumer
852
- * can prime its whole viewer graph at once. Mirrors {@link getMutualUserIds}'s
853
- * caching posture (2-minute identity-scoped cache); the follow/unfollow/block/
854
- * unblock write methods bust this entry so a local mutation is reflected
855
- * immediately. An anonymous caller resolves to empty lists.
856
- */
857
- async getViewerGraph() {
858
- try {
859
- const response = await this.makeRequest('GET', '/users/me/graph', undefined, {
860
- cache: true,
861
- cacheTTL: 2 * 60 * 1000, // 2 minutes cache
862
- });
863
- const graph = response.data;
864
- return {
865
- followingIds: graph?.followingIds || [],
866
- mutualIds: graph?.mutualIds || [],
867
- blockedIds: graph?.blockedIds || [],
868
- restrictedIds: graph?.restrictedIds || [],
869
- };
870
- }
871
- catch (error) {
872
- throw this.handleError(error);
873
- }
874
- }
875
- /**
876
- * One page of the signed-in user's Oxy notifications, newest first
877
- * (`GET /notifications`), with the unread count across all pages.
878
- */
879
- async getNotifications(params = {}) {
880
- const query = (0, apiUtils_1.buildQueryParams)({ page: params.page, limit: params.limit });
881
- return this.withAuthRetry(async () => {
882
- return await this.makeRequest('GET', '/notifications', query, {
883
- cache: false, // Don't cache notifications - always get fresh data
884
- });
885
- }, 'getNotifications');
886
- }
887
- /**
888
- * Get unread notification count
889
- */
890
- async getUnreadCount() {
891
- try {
892
- const res = await this.makeRequest('GET', '/notifications/unread-count', undefined, {
893
- cache: false, // Don't cache unread count - always get fresh data
894
- });
895
- return res.unreadCount;
896
- }
897
- catch (error) {
898
- throw this.handleError(error);
899
- }
900
- }
901
- /**
902
- * Create a notification (`POST /notifications`; the API requires a service
903
- * token whose application holds `notifications:write`). `type` is one of
904
- * `OXY_NOTIFICATION_TYPES` from `@oxy.so/contracts` — `system` for a message
905
- * from an Oxy service about the recipient's own account, with the recipient
906
- * as actor and their profile as the entity.
907
- */
908
- async createNotification(data) {
909
- try {
910
- const res = await this.makeRequest('POST', '/notifications', data, { cache: false });
911
- return res.notification;
912
- }
913
- catch (error) {
914
- throw this.handleError(error);
915
- }
916
- }
917
- /**
918
- * Mark one of the signed-in user's notifications read and return it as
919
- * stored. Scoped to the recipient server-side, so it is also the
920
- * authoritative read of a notification by id: a foreign or unknown id 404s.
921
- */
922
- async markNotificationAsRead(notificationId) {
923
- try {
924
- const res = await this.makeRequest('PUT', `/notifications/${encodeURIComponent(notificationId)}/read`, undefined, { cache: false });
925
- return res.notification;
926
- }
927
- catch (error) {
928
- throw this.handleError(error);
929
- }
930
- }
931
- /**
932
- * Mark all notifications as read
933
- */
934
- async markAllNotificationsAsRead() {
935
- try {
936
- await this.makeRequest('PUT', '/notifications/read-all', undefined, { cache: false });
937
- }
938
- catch (error) {
939
- throw this.handleError(error);
940
- }
941
- }
942
- /**
943
- * Delete notification
944
- */
945
- async deleteNotification(notificationId) {
946
- try {
947
- await this.makeRequest('DELETE', `/notifications/${notificationId}`, undefined, { cache: false });
948
- }
949
- catch (error) {
950
- throw this.handleError(error);
951
- }
952
- }
953
- };
954
- }