@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,851 +0,0 @@
1
- import { isReactNative } from '@oxy.so/protocol';
2
- import { logger } from '../logger/index.js';
3
- import { AssetUrlResolutionError, ServiceAssetMetadataError, ServiceLinkedDownloadUrlError } from '../OxyServices.errors.js';
4
- import { extractErrorStatus } from '../utils/errorUtils.js';
5
- /**
6
- * Maximum number of ids sent per `POST /assets/service/by-ids` request. Matches
7
- * the server-side batch cap (the route rejects empty or > 100 id arrays with a
8
- * 400); larger inputs are split into multiple chunked calls and merged. Mirrors
9
- * `getUsersByIds`'s `USERS_BY_IDS_CHUNK_SIZE`.
10
- */
11
- const SERVICE_ASSET_METADATA_CHUNK_SIZE = 100;
12
- /**
13
- * Maximum number of content hashes sent per `POST /assets/service/by-sha256`
14
- * request. Matches the server-side cap (the route rejects empty or > 100 hash
15
- * arrays with a 400); larger inputs are chunked and merged. Same ceiling as
16
- * {@link SERVICE_ASSET_METADATA_CHUNK_SIZE} for the forward id lookup.
17
- */
18
- const SERVICE_ASSET_METADATA_BY_SHA_CHUNK_SIZE = 100;
19
- /**
20
- * Maximum number of ids sent per `POST /assets/service/linked-url` request.
21
- * Matches that route's own cap, which is a QUARTER of the metadata routes' —
22
- * see `MAX_ASSETS_LINKED_URL` in the API for why minting download credentials is
23
- * budgeted more tightly than projecting rows.
24
- */
25
- const SERVICE_LINKED_DOWNLOAD_URL_CHUNK_SIZE = 25;
26
- /**
27
- * Lowercase hex SHA-256 digest matcher (exactly 64 hex chars). The reverse
28
- * lookup drops non-conforming hashes client-side so a single malformed value
29
- * never 400s an otherwise-valid chunk on the server.
30
- */
31
- const SHA256_HEX_PATTERN = /^[a-f0-9]{64}$/;
32
- /**
33
- * Conservative lower bound (10 min) the SDK assumes for the lifetime of the
34
- * scoped media token (`mt`) the API embeds in the stream URL it returns for a
35
- * private asset. The SDK never mints or inspects that token; this constant
36
- * exists only so the SDK's own URL cache can be sized safely BELOW the token's
37
- * real lifetime.
38
- *
39
- * The API currently mints tokens for 900s (`MEDIA_TOKEN_TTL_SECONDS` in
40
- * `packages/api/src/utils/mediaToken.ts`). Core deliberately assumes a shorter
41
- * 10-min floor rather than copying 15: core and the API are separate packages,
42
- * so core cannot observe a server-side TTL change at runtime. Under-assuming the
43
- * lifetime only ever shortens the cache (more refetches, never a dead URL), so
44
- * it stays correct even if the server lowers its TTL toward this floor. The
45
- * {@link ASSET_URL_CACHE_LIFETIME_FRACTION} discount is applied on top.
46
- */
47
- const ASSET_MEDIA_TOKEN_TTL_MS = 10 * 60 * 1000;
48
- /**
49
- * Fraction of a resolved URL's remaining lifetime the SDK is willing to keep it
50
- * cached for. A resolved URL stops working the moment its media token expires,
51
- * so caching it for its full nominal lifetime guarantees a window in which the
52
- * cache hands out an already-dead URL (clock skew, time spent in the render
53
- * pipeline, an image request queued behind others). Half the lifetime leaves a
54
- * margin at least as large as the entry's own age.
55
- */
56
- const ASSET_URL_CACHE_LIFETIME_FRACTION = 0.5;
57
- /**
58
- * Fallback URL lifetime, in seconds, assumed when the caller does not request
59
- * an explicit `expiresIn`. Mirrors the API's default signed-URL expiry; the
60
- * effective value is still clamped by {@link ASSET_MEDIA_TOKEN_TTL_MS}.
61
- */
62
- const DEFAULT_ASSET_URL_EXPIRES_IN_SECONDS = 3600;
63
- export function OxyServicesAssetsMixin(Base) {
64
- return class extends Base {
65
- constructor(...args) {
66
- super(...args);
67
- }
68
- /**
69
- * Delete file
70
- */
71
- async deleteFile(fileId) {
72
- try {
73
- return await this.makeRequest('DELETE', `/assets/${encodeURIComponent(fileId)}`, undefined, { cache: false });
74
- }
75
- catch (error) {
76
- throw this.handleError(error);
77
- }
78
- }
79
- /**
80
- * Build a synchronous, `<img src>`-ready URL for a **PUBLIC** Oxy asset.
81
- *
82
- * ## Contract — read before calling
83
- *
84
- * This is a pure string builder. It performs no network call and therefore
85
- * has **no knowledge of the asset's visibility**. It always produces the
86
- * public form: `${cloudURL}/<id>[?variant=…]`, which the CDN serves from
87
- * the public media origin only.
88
- *
89
- * Consequently:
90
- * - Call it ONLY when the asset is known to be `public` — e.g. avatars and
91
- * profile banners, which {@link uploadAvatar} / {@link uploadProfileBanner}
92
- * upload with `visibility: 'public'`.
93
- * - For an asset that may be `private` or `unlisted` — anything uploaded
94
- * through the generic {@link assetUpload} path, whose server-side default
95
- * is private — this URL resolves to a hard **404**. Use
96
- * {@link getFileDownloadUrlAsync}, which asks the API for a URL scoped to
97
- * the current caller.
98
- * - It must never guess visibility, and must never embed the caller's
99
- * bearer token: the returned string is rendered into DOM attributes,
100
- * browser network panels, HTTP caches, and logs.
101
- *
102
- * Passing `expiresIn` switches to the API-origin stream form
103
- * (`${baseURL}/assets/<id>/stream?…`) WITHOUT any credential. That form
104
- * still only serves what an unauthenticated request may see — it is not a
105
- * synchronous private-asset path, and none exists: authorization for a
106
- * private asset requires the round-trip in {@link getFileDownloadUrlAsync}.
107
- */
108
- getFileDownloadUrl(fileId, variant, expiresIn) {
109
- // Never embed the in-memory bearer token: this URL is rendered into DOM
110
- // attributes, browser network panels, caches, and logs. Public assets get
111
- // the clean CDN origin; private/authorized access goes through
112
- // `getFileDownloadUrlAsync`.
113
- if (!expiresIn) {
114
- const variantQs = variant ? `?variant=${encodeURIComponent(variant)}` : '';
115
- return `${this.getCloudURL()}/${encodeURIComponent(fileId)}${variantQs}`;
116
- }
117
- const base = this.getBaseURL();
118
- const params = new URLSearchParams();
119
- if (variant)
120
- params.set('variant', variant);
121
- params.set('expiresIn', String(expiresIn));
122
- params.set('fallback', 'placeholderVisible');
123
- const qs = params.toString();
124
- return `${base}/assets/${encodeURIComponent(fileId)}/stream${qs ? `?${qs}` : ''}`;
125
- }
126
- /**
127
- * Resolve an asset id to a URL that is valid for the CURRENT caller,
128
- * whatever the asset's visibility.
129
- *
130
- * Asks the API (`GET /assets/:id/url`) rather than guessing: a `public`
131
- * asset resolves to the CDN form, while a `private`/`unlisted` asset the
132
- * caller may read resolves to an API-origin stream URL carrying a scoped,
133
- * short-lived media token. The returned URL is passed through **unchanged**
134
- * — the SDK never rewrites, re-signs, or strips it.
135
- *
136
- * ## Failure behaviour — no CDN fallback
137
- *
138
- * Throws {@link AssetUrlResolutionError} when the API returns no URL or the
139
- * request fails (including 401/403/404). It deliberately does NOT fall back
140
- * to {@link getFileDownloadUrl}: that builder only produces the public CDN
141
- * form, so falling back would hand the caller a URL that renders as a hard
142
- * 404 for every private asset and would silently swallow the real failure.
143
- * A caller that knows an asset is public should call the synchronous
144
- * builder directly instead of relying on a fallback here.
145
- *
146
- * The resolved URL is cached per identity for well under the media token's
147
- * lifetime — see {@link getAssetUrlCacheTTL}.
148
- */
149
- async getFileDownloadUrlAsync(fileId, variant, expiresIn) {
150
- let url;
151
- try {
152
- url = await this.fetchAssetDownloadUrl(fileId, variant, this.getAssetUrlCacheTTL(expiresIn), expiresIn);
153
- }
154
- catch (error) {
155
- throw new AssetUrlResolutionError(fileId, variant, extractErrorStatus(error), error);
156
- }
157
- if (!url) {
158
- throw new AssetUrlResolutionError(fileId, variant, undefined);
159
- }
160
- return url;
161
- }
162
- /**
163
- * List user files
164
- */
165
- async listUserFiles(limit, offset) {
166
- try {
167
- const paramsObj = {};
168
- if (limit)
169
- paramsObj.limit = limit;
170
- if (offset)
171
- paramsObj.offset = offset;
172
- return await this.makeRequest('GET', '/assets', paramsObj, {
173
- cache: false,
174
- });
175
- }
176
- catch (error) {
177
- throw this.handleError(error);
178
- }
179
- }
180
- /**
181
- * Get account storage usage (server-side usage aggregated from assets)
182
- */
183
- async getAccountStorageUsage() {
184
- try {
185
- return await this.makeRequest('GET', '/storage/usage', undefined, {
186
- cache: false,
187
- });
188
- }
189
- catch (error) {
190
- throw this.handleError(error);
191
- }
192
- }
193
- /**
194
- * Get file content as text
195
- */
196
- async getFileContentAsText(fileId, variant) {
197
- try {
198
- const downloadUrl = await this.fetchAssetDownloadUrl(fileId, variant, this.getAssetUrlCacheTTL());
199
- if (!downloadUrl) {
200
- throw new Error('No download URL returned for asset');
201
- }
202
- return await this.fetchAssetContent(downloadUrl, 'text');
203
- }
204
- catch (error) {
205
- throw this.handleError(error);
206
- }
207
- }
208
- /**
209
- * Get file content as blob
210
- */
211
- async getFileContentAsBlob(fileId, variant) {
212
- try {
213
- const downloadUrl = await this.fetchAssetDownloadUrl(fileId, variant, this.getAssetUrlCacheTTL());
214
- if (!downloadUrl) {
215
- throw new Error('No download URL returned for asset');
216
- }
217
- return await this.fetchAssetContent(downloadUrl, 'blob');
218
- }
219
- catch (error) {
220
- throw this.handleError(error);
221
- }
222
- }
223
- /**
224
- * Resolve access + a caller-scoped URL for many assets — each with its OWN
225
- * requested variant — in ONE round trip via `POST /assets/batch-access`.
226
- *
227
- * `requests` is a per-file `{ fileId, variant? }` list (a `variant` of
228
- * `undefined` asks for the original). `options.expiresIn` sets the requested
229
- * media-token / signed-URL lifetime (seconds); `options.context` is the
230
- * server-side access-check context. Entries with a blank `fileId` are
231
- * dropped and exact `(fileId, variant)` duplicates are collapsed before the
232
- * request; an empty effective list performs no network call.
233
- *
234
- * The server caps the batch at 100 entries — callers that page beyond that
235
- * must chunk. Returns the raw per-file envelope (see
236
- * {@link BatchFileAccessResponse}); most callers want {@link getFileDownloadUrls},
237
- * which flattens it to just the usable URLs.
238
- */
239
- async getBatchFileAccess(requests, options) {
240
- const files = dedupeFileAccessRequests(requests);
241
- if (files.length === 0) {
242
- return { results: {} };
243
- }
244
- const body = {
245
- files,
246
- };
247
- if (typeof options?.expiresIn === 'number')
248
- body.expiresIn = options.expiresIn;
249
- if (typeof options?.context === 'string')
250
- body.context = options.context;
251
- try {
252
- return await this.makeRequest('POST', '/assets/batch-access', body, {
253
- cache: false,
254
- });
255
- }
256
- catch (error) {
257
- throw this.handleError(error);
258
- }
259
- }
260
- /**
261
- * Resolve many assets — each with its OWN variant — to caller-scoped,
262
- * `<img src>`-ready URLs in one round trip. The batch counterpart of
263
- * {@link getFileDownloadUrlAsync}, built to resolve a whole grid page at once.
264
- *
265
- * `requests` is a per-file `{ fileId, variant? }` list (e.g. `poster` for a
266
- * video, `thumb` for an image); the per-file variant RULE lives in the
267
- * caller — core just forwards what it is given. `options.expiresIn` /
268
- * `options.context` are passed through to the endpoint.
269
- *
270
- * Each returned URL is the API's own scoped form, passed through unchanged:
271
- * the public CDN URL for a public asset, or an API-origin
272
- * `/assets/:id/stream?…&mt=<media token>` URL for a private asset the caller
273
- * may read. Ids the caller cannot access (or that do not exist) are simply
274
- * OMITTED from the returned map — there is NO public-CDN fallback, so a grid
275
- * never renders a known-404 URL. Callers detect a miss by the absent key
276
- * (the map never contains an empty-string value). Keyed by `fileId`.
277
- */
278
- async getFileDownloadUrls(requests, options) {
279
- const response = await this.getBatchFileAccess(requests, options);
280
- const urls = {};
281
- for (const [id, result] of Object.entries(response.results ?? {})) {
282
- if (result.allowed && result.url) {
283
- urls[id] = result.url;
284
- }
285
- }
286
- return urls;
287
- }
288
- /**
289
- * Resolve many Oxy asset ids to their content-addressed metadata in one
290
- * round-trip per chunk via `POST /assets/service/by-ids` (body `{ ids }`).
291
- *
292
- * Returns each asset's `sha256`, `mime`, byte `size`, and `status` — built
293
- * for server-to-server callers (e.g. Mention's MTN Protocol blob-ref
294
- * resolution) that need the content hash for an asset id. Ids are
295
- * deduplicated and validated (empty/blank ids dropped) before being split
296
- * into chunks of {@link SERVICE_ASSET_METADATA_CHUNK_SIZE} (the server-side
297
- * cap). The server omits unknown/deleted ids from each chunk's `data`, so
298
- * the merged result may be shorter than the requested id list and the caller
299
- * is expected to map by `id`.
300
- *
301
- * **Service-token auth (required).** `/assets/service/by-ids` is guarded by
302
- * `serviceAuthMiddleware` + the `files:read` scope and is called via
303
- * `makeServiceRequest`, which attaches `Authorization: Bearer <serviceToken>`
304
- * (the same client that calls `POST /assets/service/cache`). The calling
305
- * client MUST be service-configured (`configureServiceAuth(apiKey,
306
- * apiSecret)`) before invoking this method; otherwise `getServiceToken()`
307
- * throws because no credentials are available. A plain user-session request
308
- * is rejected by the route's service-auth guard.
309
- *
310
- * FAILURE IS NOT ABSENCE. The server legitimately omits unknown/deleted ids,
311
- * so a short result is normal — which means a chunk that FAILED (a 429, a
312
- * timeout, a 5xx) is indistinguishable from "those assets don't exist" if it
313
- * simply contributes nothing. This method used to swallow a failed chunk and
314
- * return the rest, so every caller silently read a throttled request as "no
315
- * metadata": a backfill counted the asset as needing no update, and the
316
- * signed-record builder embedded a media item with no hash. Both reported
317
- * success while writing nothing, and the MTN chain's records are immutable.
318
- *
319
- * So a failed chunk THROWS {@link ServiceAssetMetadataError} by default,
320
- * carrying the ids it could not resolve. A caller that genuinely wants
321
- * best-effort opts in with `{ partial: true }` and gets the old behaviour
322
- * explicitly. An empty/whitespace-only input resolves immediately with `[]`
323
- * and performs no network call.
324
- *
325
- * Not cached at the SDK layer: it's a POST keyed on a multi-id body (low hit
326
- * rate), mirroring the sibling service/POST methods which never cache.
327
- */
328
- async getServiceAssetMetadataByIds(ids, options = {}) {
329
- const uniqueIds = Array.from(new Set(ids.filter((id) => typeof id === 'string' && id.trim().length > 0)));
330
- if (uniqueIds.length === 0) {
331
- return [];
332
- }
333
- const chunks = [];
334
- for (let i = 0; i < uniqueIds.length; i += SERVICE_ASSET_METADATA_CHUNK_SIZE) {
335
- chunks.push(uniqueIds.slice(i, i + SERVICE_ASSET_METADATA_CHUNK_SIZE));
336
- }
337
- // Chunks stay independent so one failure never cancels work already in
338
- // flight; the failures are collected and re-raised together below.
339
- const unresolvedIds = [];
340
- const statuses = [];
341
- let firstError;
342
- const settled = await Promise.all(chunks.map(async (chunk) => {
343
- try {
344
- const entries = await this.makeServiceRequest('POST', '/assets/service/by-ids', { ids: chunk });
345
- return Array.isArray(entries) ? entries : [];
346
- }
347
- catch (error) {
348
- const status = extractErrorStatus(error);
349
- logger.warn('getServiceAssetMetadataByIds: chunk failed', {
350
- method: 'getServiceAssetMetadataByIds',
351
- chunkSize: chunk.length,
352
- status,
353
- partial: options.partial === true,
354
- error: error instanceof Error ? error.message : String(error),
355
- });
356
- unresolvedIds.push(...chunk);
357
- if (typeof status === 'number')
358
- statuses.push(status);
359
- firstError ?? (firstError = error);
360
- return [];
361
- }
362
- }));
363
- if (unresolvedIds.length > 0 && options.partial !== true) {
364
- throw new ServiceAssetMetadataError(unresolvedIds, statuses, firstError);
365
- }
366
- return settled.flat();
367
- }
368
- /**
369
- * Mint short-lived direct download URLs for files the calling application's
370
- * own users attached to it, via `POST /assets/service/linked-url`.
371
- *
372
- * This is the ONLY path in this SDK by which a service token reaches file
373
- * BYTES. {@link getServiceAssetMetadataByIds} is metadata-only, and every
374
- * other download helper here — {@link getFileDownloadUrl},
375
- * {@link getFileDownloadUrlAsync}, {@link getBatchFileAccess} — resolves a URL
376
- * for the CURRENT USER through `makeRequest`, which is a different question: a
377
- * relying service holds no user session, and the buyer whose entitlement it is
378
- * enforcing is not a viewer Oxy knows anything about.
379
- *
380
- * **Service-token auth (required), plus the `files:linked:read` scope**, which
381
- * is NOT implied by `files:read`. The calling client must be service-configured
382
- * (`configureServiceAuth(apiKey, apiSecret)`); a user-session request is
383
- * rejected by the route's service-auth guard.
384
- *
385
- * **What the server will and will not give you.** A URL comes back only for a
386
- * file whose OWN OWNER linked it to this application (`file_links.created_by =
387
- * files.owner_user_id`). Every other id is omitted: unknown, deleted,
388
- * system-owned, linked by somebody else, or not linked here at all. So the
389
- * result is routinely shorter than the input and must be mapped by `id`.
390
- *
391
- * ABSENCE IS A REFUSAL, NOT A FACT ABOUT THE FILE, and the caller is the only
392
- * party that can tell the difference. The route deliberately cannot — it
393
- * answers identically for "no such file" and "not yours" so it leaks nothing —
394
- * which means a service must decide what to tell its user from its OWN
395
- * entitlement record, never from this response. Do not surface "file not
396
- * found" on the strength of an omission.
397
- *
398
- * FAILURE IS NOT ABSENCE EITHER, and here it cannot be opted out of: a failed
399
- * chunk throws {@link ServiceLinkedDownloadUrlError} carrying its ids, with no
400
- * `{ partial: true }` mode. Swallowing a 429 would tell a user who paid for a
401
- * file that it is not there. An empty input resolves to `[]` with no network
402
- * call.
403
- *
404
- * Never cached at the SDK layer, and that is a stronger statement than the
405
- * sibling methods' "low hit rate": each entry is a live credential for the
406
- * bytes, so caching one keeps it usable after the service has decided the
407
- * caller's entitlement ended.
408
- */
409
- async getServiceLinkedDownloadUrls(ids) {
410
- const uniqueIds = Array.from(new Set(ids.filter((id) => typeof id === 'string' && id.trim().length > 0)));
411
- if (uniqueIds.length === 0) {
412
- return [];
413
- }
414
- const chunks = [];
415
- for (let i = 0; i < uniqueIds.length; i += SERVICE_LINKED_DOWNLOAD_URL_CHUNK_SIZE) {
416
- chunks.push(uniqueIds.slice(i, i + SERVICE_LINKED_DOWNLOAD_URL_CHUNK_SIZE));
417
- }
418
- // Chunks stay independent so one failure never cancels work already in
419
- // flight; the failures are collected and re-raised together below, exactly
420
- // as in the metadata sibling.
421
- const unresolvedIds = [];
422
- const statuses = [];
423
- let firstError;
424
- const settled = await Promise.all(chunks.map(async (chunk) => {
425
- try {
426
- const entries = await this.makeServiceRequest('POST', '/assets/service/linked-url', { ids: chunk });
427
- return Array.isArray(entries) ? entries : [];
428
- }
429
- catch (error) {
430
- const status = extractErrorStatus(error);
431
- // `chunkSize` and `status`, never the ids and never a `url`: a minted
432
- // URL in a log line is a credential in a log line.
433
- logger.warn('getServiceLinkedDownloadUrls: chunk failed', {
434
- method: 'getServiceLinkedDownloadUrls',
435
- chunkSize: chunk.length,
436
- status,
437
- error: error instanceof Error ? error.message : String(error),
438
- });
439
- unresolvedIds.push(...chunk);
440
- if (typeof status === 'number')
441
- statuses.push(status);
442
- firstError ?? (firstError = error);
443
- return [];
444
- }
445
- }));
446
- if (unresolvedIds.length > 0) {
447
- throw new ServiceLinkedDownloadUrlError(unresolvedIds, statuses, firstError);
448
- }
449
- return settled.flat();
450
- }
451
- /**
452
- * Reverse content-address lookup: resolve many content `sha256` digests to
453
- * the servable Oxy asset holding each, in one round-trip per chunk via
454
- * `POST /assets/service/by-sha256` (body `{ sha256s }`).
455
- *
456
- * This is the INVERSE of {@link getServiceAssetMetadataByIds}: given a
457
- * record's `blob.sha256`, it returns the asset's `id`, `mime`, byte `size`,
458
- * `status`, and — for active, public, CDN-reachable assets only — a public
459
- * `url` (`cloud.oxy.so`). Built for server-to-server callers (e.g. Mention's
460
- * MTN materializer / node-blob sync) that hold a content hash and need to
461
- * map it back to a servable asset. Hashes are lowercased, validated against
462
- * a 64-char hex pattern (malformed entries dropped client-side), and
463
- * deduplicated before being split into chunks of
464
- * {@link SERVICE_ASSET_METADATA_BY_SHA_CHUNK_SIZE} (the server-side cap). The
465
- * server omits unknown/deleted hashes from each chunk's `data`, so the
466
- * merged result may be shorter than the requested list and the caller is
467
- * expected to map by `sha256`.
468
- *
469
- * **Service-token auth (required).** `/assets/service/by-sha256` is guarded
470
- * by `serviceAuthMiddleware` + the `files:read` scope and is called via
471
- * `makeServiceRequest` (`Authorization: Bearer <serviceToken>`, `cache:false`).
472
- * The calling client MUST be service-configured (`configureServiceAuth`)
473
- * before invoking; a plain user-session request is rejected by the route's
474
- * service-auth guard.
475
- *
476
- * Resilience: chunks are independent. A failed chunk is logged and skipped —
477
- * every entry that resolved is still returned. An empty input (or one whose
478
- * every value is malformed) resolves immediately with `[]` and performs no
479
- * network call.
480
- *
481
- * Not cached at the SDK layer: it's a POST keyed on a multi-hash body (low
482
- * hit rate), mirroring the sibling service/POST methods which never cache.
483
- */
484
- async getServiceAssetMetadataBySha256(sha256s) {
485
- const uniqueShas = Array.from(new Set(sha256s
486
- .filter((sha) => typeof sha === 'string')
487
- .map((sha) => sha.trim().toLowerCase())
488
- .filter((sha) => SHA256_HEX_PATTERN.test(sha))));
489
- if (uniqueShas.length === 0) {
490
- return [];
491
- }
492
- const chunks = [];
493
- for (let i = 0; i < uniqueShas.length; i += SERVICE_ASSET_METADATA_BY_SHA_CHUNK_SIZE) {
494
- chunks.push(uniqueShas.slice(i, i + SERVICE_ASSET_METADATA_BY_SHA_CHUNK_SIZE));
495
- }
496
- // Run chunks concurrently; a single chunk failure must not sink the rest.
497
- const settled = await Promise.all(chunks.map(async (chunk) => {
498
- try {
499
- const entries = await this.makeServiceRequest('POST', '/assets/service/by-sha256', { sha256s: chunk });
500
- return Array.isArray(entries) ? entries : [];
501
- }
502
- catch (error) {
503
- logger.warn('getServiceAssetMetadataBySha256: chunk failed, continuing with remaining chunks', {
504
- method: 'getServiceAssetMetadataBySha256',
505
- chunkSize: chunk.length,
506
- status: extractErrorStatus(error),
507
- error: error instanceof Error ? error.message : String(error),
508
- });
509
- return [];
510
- }
511
- }));
512
- return settled.flat();
513
- }
514
- /**
515
- * Upload raw file data
516
- */
517
- async uploadRawFile(file, visibility, metadata) {
518
- return this.assetUpload(file, visibility, metadata);
519
- }
520
- /**
521
- * Upload file using Central Asset Service.
522
- *
523
- * Accepts either a web File/Blob or a React Native file descriptor
524
- * ({uri, type, name, size}). RN descriptors are passed directly to
525
- * FormData.append, which handles them natively.
526
- */
527
- async assetUpload(file, visibility, metadata, onProgress) {
528
- const fileName = 'name' in file && file.name ? file.name : 'unknown';
529
- const fileSize = 'size' in file && file.size ? file.size : 0;
530
- try {
531
- const formData = new FormData();
532
- if (typeof File !== 'undefined' && file instanceof File) {
533
- formData.append('file', file, fileName);
534
- }
535
- else if (typeof Blob !== 'undefined' && file instanceof Blob) {
536
- formData.append('file', file, fileName);
537
- }
538
- else if ('uri' in file && typeof file.uri === 'string') {
539
- const descriptor = file;
540
- if (isReactNative()) {
541
- // React Native file descriptor — RN's FormData handles {uri, type, name} natively.
542
- // It reads the file from disk during the multipart request — no in-JS Blob
543
- // conversion (which would fail on Hermes for ArrayBuffer-backed Blobs).
544
- formData.append('file', descriptor, fileName);
545
- }
546
- else {
547
- // Web (browser/Node): the browser's FormData cannot read bytes from a plain
548
- // { uri } object — it would serialize "[object Object]" and the server would
549
- // store a 0-byte asset. Materialize the uri into a real Blob first. `fetch`
550
- // resolves blob:, data:, and http(s): uris on web, so all picker outputs work.
551
- const res = await fetch(descriptor.uri);
552
- if (!res.ok) {
553
- throw new Error(`Failed to read file from uri (status ${res.status})`);
554
- }
555
- const fetched = await res.blob();
556
- // Preserve the descriptor's declared MIME type when the fetched blob has none.
557
- const blob = fetched.type === '' && descriptor.type
558
- ? new Blob([fetched], { type: descriptor.type })
559
- : fetched;
560
- if (blob.size === 0) {
561
- throw new Error('Cannot upload an empty file');
562
- }
563
- formData.append('file', blob, fileName);
564
- }
565
- }
566
- else {
567
- throw new Error('Unsupported file input: expected File, Blob, or { uri, type?, name?, size? } descriptor');
568
- }
569
- if (visibility) {
570
- formData.append('visibility', visibility);
571
- }
572
- if (metadata) {
573
- formData.append('metadata', JSON.stringify(metadata));
574
- }
575
- const response = await this.getClient().request({
576
- method: 'POST',
577
- url: '/assets/upload',
578
- data: formData,
579
- cache: false,
580
- });
581
- if (onProgress && response) {
582
- onProgress(100);
583
- }
584
- return response;
585
- }
586
- catch (error) {
587
- logger.error('File upload error', error, { component: 'OxyServices.assets' });
588
- let errorMessage = 'File upload failed';
589
- if (error instanceof Error) {
590
- errorMessage = error.message || errorMessage;
591
- }
592
- else if (error && typeof error === 'object') {
593
- const errObj = error;
594
- if ('message' in errObj) {
595
- errorMessage = String(errObj.message) || errorMessage;
596
- }
597
- else if (typeof errObj.error === 'string') {
598
- errorMessage = errObj.error;
599
- }
600
- else if (errObj.data && typeof errObj.data === 'object') {
601
- const dataObj = errObj.data;
602
- if (dataObj.message) {
603
- errorMessage = String(dataObj.message);
604
- }
605
- }
606
- }
607
- else if (error) {
608
- errorMessage = String(error) || errorMessage;
609
- }
610
- const contextError = error;
611
- if (!contextError.fileContext) {
612
- contextError.fileContext = {
613
- fileName,
614
- fileSize,
615
- };
616
- }
617
- if (error instanceof Error && error.message) {
618
- const handledError = this.handleError(contextError);
619
- if (!handledError.message || handledError.message.trim() === 'An unexpected error occurred') {
620
- handledError.message = errorMessage;
621
- }
622
- throw handledError;
623
- }
624
- const newError = new Error(errorMessage);
625
- newError.fileContext = contextError.fileContext;
626
- throw this.handleError(newError);
627
- }
628
- }
629
- /**
630
- * Link asset to an entity
631
- */
632
- async assetLink(fileId, app, entityType, entityId, visibility, webhookUrl) {
633
- try {
634
- const body = { app, entityType, entityId };
635
- if (visibility)
636
- body.visibility = visibility;
637
- if (webhookUrl)
638
- body.webhookUrl = webhookUrl;
639
- return await this.makeRequest('POST', `/assets/${fileId}/links`, body, { cache: false });
640
- }
641
- catch (error) {
642
- throw this.handleError(error);
643
- }
644
- }
645
- /**
646
- * Unlink asset from an entity
647
- */
648
- async assetUnlink(fileId, app, entityType, entityId) {
649
- try {
650
- return await this.makeRequest('DELETE', `/assets/${fileId}/links`, {
651
- app,
652
- entityType,
653
- entityId
654
- }, { cache: false });
655
- }
656
- catch (error) {
657
- throw this.handleError(error);
658
- }
659
- }
660
- /**
661
- * Get asset metadata
662
- */
663
- async assetGet(fileId) {
664
- try {
665
- return await this.makeRequest('GET', `/assets/${fileId}`, undefined, {
666
- cache: true,
667
- cacheTTL: 5 * 60 * 1000,
668
- });
669
- }
670
- catch (error) {
671
- throw this.handleError(error);
672
- }
673
- }
674
- /**
675
- * Get asset URL (CDN or signed URL)
676
- */
677
- async assetGetUrl(fileId, variant, expiresIn) {
678
- try {
679
- const params = {};
680
- if (variant)
681
- params.variant = variant;
682
- if (expiresIn)
683
- params.expiresIn = expiresIn;
684
- return await this.makeRequest('GET', `/assets/${fileId}/url`, params, {
685
- cache: true,
686
- cacheTTL: this.getAssetUrlCacheTTL(expiresIn),
687
- });
688
- }
689
- catch (error) {
690
- throw this.handleError(error);
691
- }
692
- }
693
- /**
694
- * Restore asset from trash
695
- */
696
- async assetRestore(fileId) {
697
- try {
698
- const result = await this.makeRequest('POST', `/assets/${fileId}/restore`, undefined, { cache: false });
699
- // The asset metadata (trash state) changed — bust its cached read.
700
- this.clearCacheEntry(`GET:/assets/${fileId}`);
701
- return result;
702
- }
703
- catch (error) {
704
- throw this.handleError(error);
705
- }
706
- }
707
- /**
708
- * Delete asset with optional force
709
- */
710
- async assetDelete(fileId, force = false) {
711
- try {
712
- const params = force ? { force: 'true' } : undefined;
713
- const result = await this.makeRequest('DELETE', `/assets/${fileId}`, params, { cache: false });
714
- // Bust the cached metadata and every cached URL variant for the asset.
715
- this.clearCacheEntry(`GET:/assets/${fileId}`);
716
- this.clearCacheByPrefix(`GET:/assets/${fileId}/url`);
717
- return result;
718
- }
719
- catch (error) {
720
- throw this.handleError(error);
721
- }
722
- }
723
- /**
724
- * Get list of available variants for an asset
725
- */
726
- async assetGetVariants(fileId) {
727
- try {
728
- const assetData = await this.assetGet(fileId);
729
- return assetData.file?.variants || [];
730
- }
731
- catch (error) {
732
- throw this.handleError(error);
733
- }
734
- }
735
- /**
736
- * Update asset visibility
737
- */
738
- async assetUpdateVisibility(fileId, visibility) {
739
- try {
740
- const result = await this.makeRequest('PATCH', `/assets/${fileId}/visibility`, {
741
- visibility
742
- }, { cache: false });
743
- // Visibility changes both the asset metadata and the resolved URL
744
- // (public CDN vs signed). Bust the metadata read and every cached URL
745
- // variant (keyed on variant/expiresIn params).
746
- this.clearCacheEntry(`GET:/assets/${fileId}`);
747
- this.clearCacheByPrefix(`GET:/assets/${fileId}/url`);
748
- return result;
749
- }
750
- catch (error) {
751
- throw this.handleError(error);
752
- }
753
- }
754
- async uploadAvatar(file, userId, app = 'profiles') {
755
- try {
756
- const asset = await this.assetUpload(file, 'public');
757
- await this.assetLink(asset.file.id, app, 'avatar', userId, 'public');
758
- return asset;
759
- }
760
- catch (error) {
761
- throw this.handleError(error);
762
- }
763
- }
764
- async uploadProfileBanner(file, userId, app = 'profiles') {
765
- try {
766
- const asset = await this.assetUpload(file, 'public');
767
- await this.assetLink(asset.file.id, app, 'profile-banner', userId, 'public');
768
- return asset;
769
- }
770
- catch (error) {
771
- throw this.handleError(error);
772
- }
773
- }
774
- /**
775
- * How long a resolved asset URL may stay in the SDK's GET cache, in ms.
776
- *
777
- * A resolved private-asset URL dies the instant its scoped media token
778
- * expires (~{@link ASSET_MEDIA_TOKEN_TTL_MS}). Caching it for its full
779
- * nominal lifetime would leave a window where the cache serves an
780
- * already-dead URL (clock skew, render-pipeline latency, an image request
781
- * queued behind others). So the TTL is (a) never longer than the token's
782
- * lifetime and (b) discounted to {@link ASSET_URL_CACHE_LIFETIME_FRACTION}
783
- * of that bound — comfortably below the token TTL by construction.
784
- */
785
- getAssetUrlCacheTTL(expiresIn) {
786
- const requestedLifetimeMs = (expiresIn ?? DEFAULT_ASSET_URL_EXPIRES_IN_SECONDS) * 1000;
787
- const boundedLifetimeMs = Math.min(requestedLifetimeMs, ASSET_MEDIA_TOKEN_TTL_MS);
788
- return Math.floor(boundedLifetimeMs * ASSET_URL_CACHE_LIFETIME_FRACTION);
789
- }
790
- async fetchAssetDownloadUrl(fileId, variant, cacheTTL, expiresIn) {
791
- const params = {};
792
- if (variant)
793
- params.variant = variant;
794
- if (expiresIn)
795
- params.expiresIn = expiresIn;
796
- const urlRes = await this.makeRequest('GET', `/assets/${encodeURIComponent(fileId)}/url`, Object.keys(params).length ? params : undefined, {
797
- cache: true,
798
- // Cap the cached URL well below the media token's lifetime. The
799
- // response body is a scoped, expiring URL; over-caching it serves a
800
- // dead URL after the token expires (see getAssetUrlCacheTTL).
801
- cacheTTL: cacheTTL ?? this.getAssetUrlCacheTTL(expiresIn),
802
- });
803
- return urlRes?.url || null;
804
- }
805
- async fetchAssetContent(url, type) {
806
- const response = await fetch(url, {
807
- credentials: shouldSendAssetCredentials(url, this.getBaseURL()) ? 'include' : 'omit',
808
- });
809
- if (!response?.ok) {
810
- throw new Error(`Failed to fetch asset content (status ${response?.status})`);
811
- }
812
- return type === 'text' ? response.text() : response.blob();
813
- }
814
- };
815
- }
816
- /**
817
- * Normalize the per-file batch-access request list: drop entries with a blank
818
- * `fileId` and collapse exact `(fileId, variant)` duplicates (first occurrence
819
- * wins, preserving order). Two entries for the SAME `fileId` with DIFFERENT
820
- * variants are intentionally kept — but note the response is keyed by `fileId`,
821
- * so a caller that needs two variants of one file must issue separate calls.
822
- */
823
- function dedupeFileAccessRequests(requests) {
824
- const seen = new Set();
825
- const out = [];
826
- for (const req of requests) {
827
- if (typeof req?.fileId !== 'string' || req.fileId.trim().length === 0) {
828
- continue;
829
- }
830
- const key = `${req.fileId}\u0000${req.variant ?? ''}`;
831
- if (seen.has(key)) {
832
- continue;
833
- }
834
- seen.add(key);
835
- out.push(req.variant === undefined ? { fileId: req.fileId } : { fileId: req.fileId, variant: req.variant });
836
- }
837
- return out;
838
- }
839
- /**
840
- * Only send ambient credentials (cookies) when the asset URL is same-origin with
841
- * the configured API base. Caller-supplied cross-origin asset URLs must not leak
842
- * the user's cookies to arbitrary hosts.
843
- */
844
- function shouldSendAssetCredentials(url, baseURL) {
845
- try {
846
- return new URL(url).origin === new URL(baseURL).origin;
847
- }
848
- catch {
849
- return false;
850
- }
851
- }