@oxy.so/core 4.5.0-oxy-one.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/HttpService.js +63 -19
  3. package/dist/cjs/api/accounts.js +10 -3
  4. package/dist/cjs/api/agency.js +3 -1
  5. package/dist/cjs/api/apps.js +15 -4
  6. package/dist/cjs/api/assets.js +49 -12
  7. package/dist/cjs/api/auth.js +37 -11
  8. package/dist/cjs/api/billing.js +24 -7
  9. package/dist/cjs/api/civic.js +14 -4
  10. package/dist/cjs/api/follows.js +9 -2
  11. package/dist/cjs/api/identity.js +31 -9
  12. package/dist/cjs/api/nodes.js +3 -1
  13. package/dist/cjs/api/privacy.js +8 -2
  14. package/dist/cjs/api/session.js +15 -4
  15. package/dist/cjs/api/store.js +15 -5
  16. package/dist/cjs/api/topics.js +10 -3
  17. package/dist/cjs/api/users.js +16 -4
  18. package/dist/cjs/boot/sessionColdBoot.js +40 -13
  19. package/dist/cjs/constants/version.js +6 -6
  20. package/dist/cjs/crypto/identityMarker.js +3 -1
  21. package/dist/cjs/crypto/identityProof.js +6 -1
  22. package/dist/cjs/crypto/keyManager.js +87 -32
  23. package/dist/cjs/crypto/recoveryPhrase.js +2 -2
  24. package/dist/cjs/crypto/signatureService.js +3 -4
  25. package/dist/cjs/i18n/index.js +16 -3
  26. package/dist/cjs/i18n/locales/ar-SA.js +366 -366
  27. package/dist/cjs/i18n/locales/ca-ES.js +366 -366
  28. package/dist/cjs/i18n/locales/de-DE.js +366 -366
  29. package/dist/cjs/i18n/locales/en-US.js +1994 -1994
  30. package/dist/cjs/i18n/locales/es-ES.js +1994 -1994
  31. package/dist/cjs/i18n/locales/fr-FR.js +366 -366
  32. package/dist/cjs/i18n/locales/it-IT.js +366 -366
  33. package/dist/cjs/i18n/locales/ja-JP.js +366 -366
  34. package/dist/cjs/i18n/locales/ko-KR.js +366 -366
  35. package/dist/cjs/i18n/locales/pt-PT.js +366 -366
  36. package/dist/cjs/i18n/locales/zh-CN.js +366 -366
  37. package/dist/cjs/inference/OxyInferenceClient.js +12 -18
  38. package/dist/cjs/models/interfaces.js +11 -11
  39. package/dist/cjs/server/OxyServer.js +86 -28
  40. package/dist/cjs/server/agentAccount.js +6 -2
  41. package/dist/cjs/server/aliaMachineCredential.js +39 -14
  42. package/dist/cjs/server/auth.js +5 -4
  43. package/dist/cjs/server/capabilityTicket.js +5 -5
  44. package/dist/cjs/server/index.js +2 -1
  45. package/dist/cjs/server/liveCapabilityTicket.js +4 -1
  46. package/dist/cjs/server/middleware.js +61 -42
  47. package/dist/cjs/server/namespaces.js +28 -7
  48. package/dist/cjs/server/requesterAssertion.js +36 -30
  49. package/dist/cjs/server/serviceTokenLifetime.js +7 -4
  50. package/dist/cjs/server/traffic.js +53 -14
  51. package/dist/cjs/server/trafficNodeHttp.js +33 -8
  52. package/dist/cjs/server/workloadIdentity.client.js +4 -0
  53. package/dist/cjs/server/workloadIdentity.js +28 -1
  54. package/dist/cjs/session/SessionClient.js +54 -17
  55. package/dist/cjs/session/accountDelegationAccess.js +4 -6
  56. package/dist/cjs/session/accountDialogController.js +1 -1
  57. package/dist/cjs/session/authStateStore.js +18 -9
  58. package/dist/cjs/session/identityPin.js +6 -2
  59. package/dist/cjs/session/refresh.js +81 -23
  60. package/dist/cjs/session/sharedDeviceCredential.js +28 -15
  61. package/dist/cjs/shared/utils/errorUtils.js +1 -1
  62. package/dist/cjs/shared/utils/networkUtils.js +1 -1
  63. package/dist/cjs/shared/utils/themeUtils.js +1 -1
  64. package/dist/cjs/utils/accountCacheSweep.js +3 -1
  65. package/dist/cjs/utils/accountUtils.js +1 -3
  66. package/dist/cjs/utils/asyncUtils.js +1 -1
  67. package/dist/cjs/utils/authHelpers.js +2 -1
  68. package/dist/cjs/utils/avatarUtils.js +4 -2
  69. package/dist/cjs/utils/cache.js +1 -1
  70. package/dist/cjs/utils/cacheKey.js +3 -1
  71. package/dist/cjs/utils/deviceManager.js +4 -4
  72. package/dist/cjs/utils/errorUtils.js +6 -4
  73. package/dist/cjs/utils/languageUtils.js +404 -57
  74. package/dist/cjs/utils/profileLinks.js +1 -3
  75. package/dist/cjs/utils/requestUtils.js +7 -1
  76. package/dist/cjs/utils/userIdentity.js +1 -1
  77. package/dist/cjs/utils/validationUtils.js +5 -6
  78. package/dist/esm/HttpService.js +64 -20
  79. package/dist/esm/api/accounts.js +11 -4
  80. package/dist/esm/api/agency.js +3 -1
  81. package/dist/esm/api/apps.js +15 -4
  82. package/dist/esm/api/assets.js +49 -12
  83. package/dist/esm/api/auth.js +37 -11
  84. package/dist/esm/api/billing.js +25 -8
  85. package/dist/esm/api/civic.js +14 -4
  86. package/dist/esm/api/follows.js +9 -2
  87. package/dist/esm/api/identity.js +31 -9
  88. package/dist/esm/api/nodes.js +3 -1
  89. package/dist/esm/api/privacy.js +8 -2
  90. package/dist/esm/api/session.js +15 -4
  91. package/dist/esm/api/store.js +15 -5
  92. package/dist/esm/api/topics.js +10 -3
  93. package/dist/esm/api/users.js +16 -4
  94. package/dist/esm/boot/sessionColdBoot.js +41 -14
  95. package/dist/esm/constants/version.js +6 -6
  96. package/dist/esm/crypto/identityMarker.js +3 -1
  97. package/dist/esm/crypto/identityProof.js +6 -1
  98. package/dist/esm/crypto/internal.js +1 -1
  99. package/dist/esm/crypto/keyManager.js +87 -32
  100. package/dist/esm/crypto/recoveryPhrase.js +2 -2
  101. package/dist/esm/crypto/signatureService.js +3 -4
  102. package/dist/esm/i18n/index.js +16 -3
  103. package/dist/esm/i18n/locales/ar-SA.js +366 -366
  104. package/dist/esm/i18n/locales/ca-ES.js +366 -366
  105. package/dist/esm/i18n/locales/de-DE.js +366 -366
  106. package/dist/esm/i18n/locales/en-US.js +1994 -1994
  107. package/dist/esm/i18n/locales/es-ES.js +1994 -1994
  108. package/dist/esm/i18n/locales/fr-FR.js +366 -366
  109. package/dist/esm/i18n/locales/it-IT.js +366 -366
  110. package/dist/esm/i18n/locales/ja-JP.js +366 -366
  111. package/dist/esm/i18n/locales/ko-KR.js +366 -366
  112. package/dist/esm/i18n/locales/pt-PT.js +366 -366
  113. package/dist/esm/i18n/locales/zh-CN.js +366 -366
  114. package/dist/esm/index.js +1 -1
  115. package/dist/esm/inference/OxyInferenceClient.js +13 -19
  116. package/dist/esm/models/interfaces.js +11 -11
  117. package/dist/esm/server/OxyServer.js +87 -29
  118. package/dist/esm/server/agentAccount.js +6 -2
  119. package/dist/esm/server/aliaMachineCredential.js +39 -14
  120. package/dist/esm/server/auth.js +6 -5
  121. package/dist/esm/server/capabilityTicket.js +6 -6
  122. package/dist/esm/server/index.js +5 -5
  123. package/dist/esm/server/liveCapabilityTicket.js +6 -3
  124. package/dist/esm/server/middleware.js +62 -43
  125. package/dist/esm/server/namespaces.js +31 -10
  126. package/dist/esm/server/requesterAssertion.js +36 -30
  127. package/dist/esm/server/serviceTokenLifetime.js +7 -4
  128. package/dist/esm/server/traffic.js +55 -16
  129. package/dist/esm/server/trafficNodeHttp.js +34 -9
  130. package/dist/esm/server/userInvalidation.js +1 -1
  131. package/dist/esm/server/workloadIdentity.client.js +3 -0
  132. package/dist/esm/server/workloadIdentity.js +27 -1
  133. package/dist/esm/session/SessionClient.js +54 -17
  134. package/dist/esm/session/accountDelegationAccess.js +5 -7
  135. package/dist/esm/session/accountDialogController.js +1 -1
  136. package/dist/esm/session/authStateStore.js +18 -9
  137. package/dist/esm/session/identityPin.js +6 -2
  138. package/dist/esm/session/refresh.js +82 -24
  139. package/dist/esm/session/sharedDeviceCredential.js +28 -15
  140. package/dist/esm/shared/utils/errorUtils.js +1 -1
  141. package/dist/esm/shared/utils/networkUtils.js +1 -1
  142. package/dist/esm/shared/utils/themeUtils.js +1 -1
  143. package/dist/esm/utils/accountCacheSweep.js +3 -1
  144. package/dist/esm/utils/accountUtils.js +1 -3
  145. package/dist/esm/utils/asyncUtils.js +1 -1
  146. package/dist/esm/utils/authHelpers.js +2 -1
  147. package/dist/esm/utils/avatarUtils.js +4 -2
  148. package/dist/esm/utils/cache.js +1 -1
  149. package/dist/esm/utils/cacheKey.js +3 -1
  150. package/dist/esm/utils/deviceManager.js +4 -4
  151. package/dist/esm/utils/errorUtils.js +6 -4
  152. package/dist/esm/utils/languageUtils.js +404 -57
  153. package/dist/esm/utils/profileLinks.js +1 -3
  154. package/dist/esm/utils/requestUtils.js +7 -1
  155. package/dist/esm/utils/userIdentity.js +1 -1
  156. package/dist/esm/utils/validationUtils.js +5 -6
  157. package/dist/types/HttpService.d.ts +1 -1
  158. package/dist/types/api/accounts.d.ts +1 -1
  159. package/dist/types/api/apps.d.ts +4 -4
  160. package/dist/types/api/assets.d.ts +2 -0
  161. package/dist/types/api/auth.d.ts +8 -3
  162. package/dist/types/crypto/internal.d.ts +1 -1
  163. package/dist/types/index.d.ts +4 -4
  164. package/dist/types/server/index.d.ts +6 -6
  165. package/dist/types/server/requesterAssertion.d.ts +2 -2
  166. package/dist/types/server/workloadIdentity.client.d.ts +5 -1
  167. package/dist/types/server/workloadIdentity.d.ts +26 -0
  168. package/dist/types/session/accountDelegationAccess.d.ts +1 -1
  169. package/dist/types/session/index.d.ts +1 -1
  170. package/dist/types/utils/userIdentity.d.ts +1 -1
  171. package/dist/types/utils/validationUtils.d.ts +4 -5
  172. package/package.json +2 -3
  173. package/src/HttpService.ts +183 -53
  174. package/src/OxyServices.errors.ts +7 -3
  175. package/src/OxyServices.ts +6 -2
  176. package/src/api/accounts.ts +76 -26
  177. package/src/api/agency.ts +24 -9
  178. package/src/api/appData.ts +12 -2
  179. package/src/api/apps.ts +81 -31
  180. package/src/api/assets.ts +122 -40
  181. package/src/api/auth.ts +154 -79
  182. package/src/api/billing.ts +112 -65
  183. package/src/api/civic.ts +61 -19
  184. package/src/api/contacts.ts +4 -1
  185. package/src/api/devices.ts +54 -21
  186. package/src/api/follows.ts +88 -31
  187. package/src/api/identity.ts +101 -33
  188. package/src/api/linkedAccounts.ts +26 -8
  189. package/src/api/nodes.ts +18 -6
  190. package/src/api/notifications.ts +26 -6
  191. package/src/api/privacy.ts +42 -8
  192. package/src/api/reputation.ts +18 -7
  193. package/src/api/session.ts +23 -5
  194. package/src/api/store.ts +81 -31
  195. package/src/api/topics.ts +18 -6
  196. package/src/api/users.ts +98 -35
  197. package/src/boot/sessionColdBoot.ts +60 -19
  198. package/src/civic/payloads.ts +1 -4
  199. package/src/client/context.ts +6 -1
  200. package/src/constants/version.ts +7 -6
  201. package/src/crypto/aead.ts +1 -5
  202. package/src/crypto/ecdh.ts +1 -4
  203. package/src/crypto/identityDerivations.ts +5 -1
  204. package/src/crypto/identityMarker.ts +3 -1
  205. package/src/crypto/identityProof.ts +6 -1
  206. package/src/crypto/index.ts +11 -11
  207. package/src/crypto/internal.ts +6 -1
  208. package/src/crypto/keyManager.ts +348 -98
  209. package/src/crypto/recoveryPhrase.ts +14 -9
  210. package/src/crypto/registrationPow.ts +1 -1
  211. package/src/crypto/signatureService.ts +14 -6
  212. package/src/i18n/accountCategoryLabels.ts +1 -4
  213. package/src/i18n/accountRoleLabels.ts +1 -4
  214. package/src/i18n/index.ts +25 -7
  215. package/src/i18n/locales/ar-SA.ts +375 -366
  216. package/src/i18n/locales/ca-ES.ts +382 -366
  217. package/src/i18n/locales/de-DE.ts +387 -366
  218. package/src/i18n/locales/en-US.ts +2034 -1994
  219. package/src/i18n/locales/es-ES.ts +2043 -1994
  220. package/src/i18n/locales/fr-FR.ts +387 -366
  221. package/src/i18n/locales/it-IT.ts +380 -366
  222. package/src/i18n/locales/ja-JP.ts +380 -366
  223. package/src/i18n/locales/ko-KR.ts +377 -366
  224. package/src/i18n/locales/pt-PT.ts +383 -366
  225. package/src/i18n/locales/zh-CN.ts +373 -366
  226. package/src/i18n/trustTierLabels.ts +1 -4
  227. package/src/index.ts +371 -349
  228. package/src/inference/OxyInferenceClient.ts +784 -780
  229. package/src/models/interfaces.ts +30 -27
  230. package/src/server/OxyServer.ts +227 -68
  231. package/src/server/agentAccount.ts +8 -2
  232. package/src/server/aliaMachineCredential.ts +57 -16
  233. package/src/server/auth.ts +9 -5
  234. package/src/server/capabilityTicket.ts +30 -21
  235. package/src/server/index.ts +29 -6
  236. package/src/server/liveCapabilityTicket.ts +31 -9
  237. package/src/server/middleware.ts +212 -121
  238. package/src/server/namespaces.ts +247 -94
  239. package/src/server/rateLimit.ts +2 -4
  240. package/src/server/requesterAssertion.ts +93 -54
  241. package/src/server/serviceTokenLifetime.ts +9 -4
  242. package/src/server/traffic.ts +117 -23
  243. package/src/server/trafficNodeHttp.ts +61 -14
  244. package/src/server/userInvalidation.ts +1 -4
  245. package/src/server/workloadIdentity.client.ts +12 -1
  246. package/src/server/workloadIdentity.ts +52 -5
  247. package/src/session/SessionClient.ts +170 -49
  248. package/src/session/accountDelegationAccess.ts +24 -31
  249. package/src/session/accountDialogController.ts +59 -14
  250. package/src/session/accountSwitchTargets.ts +10 -15
  251. package/src/session/authStateStore.ts +121 -81
  252. package/src/session/deviceDirectory.ts +1 -3
  253. package/src/session/identityPin.ts +10 -11
  254. package/src/session/identitySession.ts +3 -1
  255. package/src/session/index.ts +87 -82
  256. package/src/session/refresh.ts +138 -44
  257. package/src/session/sessionClientHost.ts +1 -3
  258. package/src/session/sharedDeviceCredential.ts +35 -14
  259. package/src/session/socketLoader.ts +9 -2
  260. package/src/shared/utils/errorUtils.ts +5 -2
  261. package/src/shared/utils/networkUtils.ts +5 -8
  262. package/src/shared/utils/themeUtils.ts +2 -6
  263. package/src/types/buffer.d.ts +66 -21
  264. package/src/types/expo-secure-store.d.ts +5 -1
  265. package/src/utils/accountCacheSweep.ts +4 -5
  266. package/src/utils/accountUtils.ts +107 -108
  267. package/src/utils/apiUtils.ts +3 -3
  268. package/src/utils/asyncUtils.ts +2 -2
  269. package/src/utils/authHelpers.ts +10 -5
  270. package/src/utils/avatarUtils.ts +11 -6
  271. package/src/utils/cache.ts +9 -10
  272. package/src/utils/cacheKey.ts +5 -1
  273. package/src/utils/coldBoot.ts +1 -3
  274. package/src/utils/commonsDelivery.ts +1 -4
  275. package/src/utils/deviceManager.ts +15 -14
  276. package/src/utils/errorUtils.ts +68 -86
  277. package/src/utils/languageUtils.ts +407 -58
  278. package/src/utils/oauthPkce.ts +1 -4
  279. package/src/utils/platform.ts +0 -1
  280. package/src/utils/profileLinks.ts +2 -5
  281. package/src/utils/requestUtils.ts +18 -14
  282. package/src/utils/sessionUtils.ts +34 -33
  283. package/src/utils/userHandle.ts +3 -1
  284. package/src/utils/userIdentity.ts +1 -1
  285. package/src/utils/validationUtils.ts +11 -9
package/src/api/assets.ts CHANGED
@@ -52,6 +52,13 @@ const DEFAULT_ASSET_URL_EXPIRES_IN_SECONDS = 3600;
52
52
 
53
53
  const ASSET_TTL = 5 * 60 * 1000;
54
54
 
55
+ /**
56
+ * Default bound on one `POST /assets/upload`, in ms. The client's per-request
57
+ * default (5s) is sized for JSON calls; a video sent over a phone connection
58
+ * needs minutes, and timing it out at 5s failed every upload past a few MB.
59
+ */
60
+ const ASSET_UPLOAD_TIMEOUT_MS = 10 * 60 * 1000;
61
+
55
62
  /**
56
63
  * How long a resolved asset URL may stay in the SDK's GET cache, in ms: never
57
64
  * longer than the media token's lifetime, and discounted below it.
@@ -66,7 +73,10 @@ export function assetUrlCacheTTL(expiresIn?: number): number {
66
73
  export type AssetRecord = Omit<Asset, 'visibility'> & { visibility?: FileVisibility };
67
74
 
68
75
  /** The asset `POST /assets/upload` returns. */
69
- export type UploadedAsset = Pick<Asset, 'id' | 'sha256' | 'size' | 'mime' | 'ext' | 'visibility' | 'links' | 'variants'> & {
76
+ export type UploadedAsset = Pick<
77
+ Asset,
78
+ 'id' | 'sha256' | 'size' | 'mime' | 'ext' | 'visibility' | 'links' | 'variants'
79
+ > & {
70
80
  originalName?: string;
71
81
  metadata?: AssetMetadata;
72
82
  };
@@ -85,6 +95,8 @@ export interface AssetUploadOptions {
85
95
  metadata?: AssetMetadata;
86
96
  /** Called with `100` once the upload completes. */
87
97
  onProgress?: (progress: number) => void;
98
+ /** Bound on the whole upload, in ms. Default {@link ASSET_UPLOAD_TIMEOUT_MS}. */
99
+ timeout?: number;
88
100
  }
89
101
 
90
102
  export interface AssetLinkTarget {
@@ -108,13 +120,23 @@ export class AssetsApi {
108
120
  const target = new URL(init.uploadUrl);
109
121
  if (target.protocol !== 'https:') throw new Error('Presigned uploads require HTTPS');
110
122
  const headers = new Headers(init.requiredHeaders);
111
- headers.forEach((_value,name) => {
112
- if (!['if-none-match','content-type','x-amz-checksum-sha256','cache-control'].includes(name.toLowerCase()))
123
+ headers.forEach((_value, name) => {
124
+ if (
125
+ !['if-none-match', 'content-type', 'x-amz-checksum-sha256', 'cache-control'].includes(
126
+ name.toLowerCase(),
127
+ )
128
+ )
113
129
  throw new Error('Unsupported required upload header');
114
130
  });
115
- if (body.type && !headers.has('Content-Type')) headers.set('Content-Type',body.type);
116
- const result = await fetch(target.toString(),{method:'PUT',body,headers,credentials:'omit',redirect:'error'});
117
- if(!result.ok)throw new Error(`Presigned upload failed (${result.status})`);
131
+ if (body.type && !headers.has('Content-Type')) headers.set('Content-Type', body.type);
132
+ const result = await fetch(target.toString(), {
133
+ method: 'PUT',
134
+ body,
135
+ headers,
136
+ credentials: 'omit',
137
+ redirect: 'error',
138
+ });
139
+ if (!result.ok) throw new Error(`Presigned upload failed (${result.status})`);
118
140
  }
119
141
 
120
142
  // ── Upload ───────────────────────────────────────────────────────────────
@@ -128,12 +150,18 @@ export class AssetsApi {
128
150
  * read by FormData (it would upload `[object Object]` — a 0-byte asset), so
129
151
  * the uri is materialised into a Blob first; an empty result throws.
130
152
  */
131
- async upload(file: AssetUploadInput, options: AssetUploadOptions = {}): Promise<{ file: UploadedAsset }> {
153
+ async upload(
154
+ file: AssetUploadInput,
155
+ options: AssetUploadOptions = {},
156
+ ): Promise<{ file: UploadedAsset }> {
132
157
  const fileName = 'name' in file && file.name ? file.name : 'unknown';
133
158
  const fileSize = 'size' in file && file.size ? file.size : 0;
134
159
 
135
160
  const formData = new FormData();
136
- if ((typeof File !== 'undefined' && file instanceof File) || (typeof Blob !== 'undefined' && file instanceof Blob)) {
161
+ if (
162
+ (typeof File !== 'undefined' && file instanceof File) ||
163
+ (typeof Blob !== 'undefined' && file instanceof Blob)
164
+ ) {
137
165
  formData.append('file', file, fileName);
138
166
  } else if ('uri' in file && typeof (file as RNFileDescriptor).uri === 'string') {
139
167
  const descriptor = file as RNFileDescriptor;
@@ -147,25 +175,41 @@ export class AssetsApi {
147
175
  throw new Error(`Failed to read file from uri (status ${res.status})`);
148
176
  }
149
177
  const fetched = await res.blob();
150
- const blob = fetched.type === '' && descriptor.type ? new Blob([fetched], { type: descriptor.type }) : fetched;
178
+ const blob =
179
+ fetched.type === '' && descriptor.type
180
+ ? new Blob([fetched], { type: descriptor.type })
181
+ : fetched;
151
182
  if (blob.size === 0) {
152
183
  throw new Error('Cannot upload an empty file');
153
184
  }
154
185
  formData.append('file', blob, fileName);
155
186
  }
156
187
  } else {
157
- throw new Error('Unsupported file input: expected File, Blob, or { uri, type?, name?, size? } descriptor');
188
+ throw new Error(
189
+ 'Unsupported file input: expected File, Blob, or { uri, type?, name?, size? } descriptor',
190
+ );
158
191
  }
159
192
  if (options.visibility) formData.append('visibility', options.visibility);
160
193
  if (options.metadata) formData.append('metadata', JSON.stringify(options.metadata));
161
194
 
162
195
  try {
163
- const response = await this.ctx.request<{ file: UploadedAsset }>('POST', '/assets/upload', formData, { cache: false });
196
+ const response = await this.ctx.request<{ file: UploadedAsset }>(
197
+ 'POST',
198
+ '/assets/upload',
199
+ formData,
200
+ {
201
+ cache: false,
202
+ timeout: options.timeout ?? ASSET_UPLOAD_TIMEOUT_MS,
203
+ },
204
+ );
164
205
  options.onProgress?.(100);
165
206
  return response;
166
207
  } catch (error) {
167
208
  logger.error('File upload error', error, { component: 'oxy.assets' });
168
- (error as Error & { fileContext?: Record<string, unknown> }).fileContext = { fileName, fileSize };
209
+ (error as Error & { fileContext?: Record<string, unknown> }).fileContext = {
210
+ fileName,
211
+ fileSize,
212
+ };
169
213
  throw error;
170
214
  }
171
215
  }
@@ -174,9 +218,17 @@ export class AssetsApi {
174
218
  * Upload a public avatar and link it to `userId`'s profile. Does not change
175
219
  * the profile's `avatar` field — set it with `users.updateMe`.
176
220
  */
177
- async uploadAvatar(file: AssetUploadInput, userId: string, app = 'profiles'): Promise<{ file: UploadedAsset }> {
221
+ async uploadAvatar(
222
+ file: AssetUploadInput,
223
+ userId: string,
224
+ app = 'profiles',
225
+ ): Promise<{ file: UploadedAsset }> {
178
226
  const asset = await this.upload(file, { visibility: 'public' });
179
- await this.link(asset.file.id, { app, entityType: 'avatar', entityId: userId }, { visibility: 'public' });
227
+ await this.link(
228
+ asset.file.id,
229
+ { app, entityType: 'avatar', entityId: userId },
230
+ { visibility: 'public' },
231
+ );
180
232
  return asset;
181
233
  }
182
234
 
@@ -188,19 +240,31 @@ export class AssetsApi {
188
240
  target: AssetLinkTarget,
189
241
  options: { visibility?: FileVisibility; webhookUrl?: string } = {},
190
242
  ): Promise<{ assetId: string; file: AssetLinkState }> {
191
- const body: AssetLinkTarget & { visibility?: FileVisibility; webhookUrl?: string } = { ...target };
243
+ const body: AssetLinkTarget & { visibility?: FileVisibility; webhookUrl?: string } = {
244
+ ...target,
245
+ };
192
246
  if (options.visibility) body.visibility = options.visibility;
193
247
  if (options.webhookUrl) body.webhookUrl = options.webhookUrl;
194
- const res = await this.ctx.request<{ assetId: string; file: AssetLinkState }>('POST', `/assets/${enc(fileId)}/links`, body, {
195
- cache: false,
196
- });
248
+ const res = await this.ctx.request<{ assetId: string; file: AssetLinkState }>(
249
+ 'POST',
250
+ `/assets/${enc(fileId)}/links`,
251
+ body,
252
+ {
253
+ cache: false,
254
+ },
255
+ );
197
256
  this.ctx.oxy.cache.delete(`GET:/assets/${enc(fileId)}`);
198
257
  return res;
199
258
  }
200
259
 
201
260
  /** Remove an asset's link to an entity. */
202
261
  async unlink(fileId: string, target: AssetLinkTarget): Promise<{ file: AssetLinkState }> {
203
- const res = await this.ctx.request<{ file: AssetLinkState }>('DELETE', `/assets/${enc(fileId)}/links`, target, { cache: false });
262
+ const res = await this.ctx.request<{ file: AssetLinkState }>(
263
+ 'DELETE',
264
+ `/assets/${enc(fileId)}/links`,
265
+ target,
266
+ { cache: false },
267
+ );
204
268
  this.ctx.oxy.cache.delete(`GET:/assets/${enc(fileId)}`);
205
269
  return res;
206
270
  }
@@ -209,11 +273,16 @@ export class AssetsApi {
209
273
 
210
274
  /** An asset's record: size, mime, visibility, links, variants. */
211
275
  async get(fileId: string): Promise<{ assetId: string; file: AssetRecord }> {
212
- return this.ctx.request('GET', `/assets/${enc(fileId)}`, undefined, { cache: true, cacheTTL: ASSET_TTL });
276
+ return this.ctx.request('GET', `/assets/${enc(fileId)}`, undefined, {
277
+ cache: true,
278
+ cacheTTL: ASSET_TTL,
279
+ });
213
280
  }
214
281
 
215
282
  /** The signed-in user's files, newest first. */
216
- async list(params: { limit?: number; offset?: number } = {}): Promise<{ files: AssetRecord[]; total: number; hasMore: boolean }> {
283
+ async list(
284
+ params: { limit?: number; offset?: number } = {},
285
+ ): Promise<{ files: AssetRecord[]; total: number; hasMore: boolean }> {
217
286
  const query: Record<string, number> = {};
218
287
  if (params.limit) query.limit = params.limit;
219
288
  if (params.offset) query.offset = params.offset;
@@ -222,7 +291,9 @@ export class AssetsApi {
222
291
 
223
292
  /** The account's storage usage, aggregated from its assets. */
224
293
  async usage(): Promise<AccountStorageUsageResponse> {
225
- return this.ctx.request<AccountStorageUsageResponse>('GET', '/storage/usage', undefined, { cache: false });
294
+ return this.ctx.request<AccountStorageUsageResponse>('GET', '/storage/usage', undefined, {
295
+ cache: false,
296
+ });
226
297
  }
227
298
 
228
299
  // ── URLs ─────────────────────────────────────────────────────────────────
@@ -309,7 +380,9 @@ export class AssetsApi {
309
380
  const body: { files: typeof files; expiresIn?: number; context?: string } = { files };
310
381
  if (typeof options?.expiresIn === 'number') body.expiresIn = options.expiresIn;
311
382
  if (typeof options?.context === 'string') body.context = options.context;
312
- return this.ctx.request<BatchFileAccessResponse>('POST', '/assets/batch-access', body, { cache: false });
383
+ return this.ctx.request<BatchFileAccessResponse>('POST', '/assets/batch-access', body, {
384
+ cache: false,
385
+ });
313
386
  }
314
387
 
315
388
  // ── Content ──────────────────────────────────────────────────────────────
@@ -334,19 +407,20 @@ export class AssetsApi {
334
407
  */
335
408
  async delete(fileId: string, options: { force?: boolean } = {}): Promise<AssetDeleteResult> {
336
409
  const url = `/assets/${enc(fileId)}${options.force ? '?force=true' : ''}`;
337
- const res = await this.ctx.request<AssetDeleteResult>('DELETE', url, undefined, { cache: false });
410
+ const res = await this.ctx.request<AssetDeleteResult>('DELETE', url, undefined, {
411
+ cache: false,
412
+ });
338
413
  this.evict(fileId);
339
414
  return res;
340
415
  }
341
416
 
342
417
  /** Restore an asset from the trash. */
343
- async restore(fileId: string): Promise<{ file: { id: string; status: Asset['status']; usageCount: number } }> {
344
- const res = await this.ctx.request<{ file: { id: string; status: Asset['status']; usageCount: number } }>(
345
- 'POST',
346
- `/assets/${enc(fileId)}/restore`,
347
- undefined,
348
- { cache: false },
349
- );
418
+ async restore(
419
+ fileId: string,
420
+ ): Promise<{ file: { id: string; status: Asset['status']; usageCount: number } }> {
421
+ const res = await this.ctx.request<{
422
+ file: { id: string; status: Asset['status']; usageCount: number };
423
+ }>('POST', `/assets/${enc(fileId)}/restore`, undefined, { cache: false });
350
424
  this.ctx.oxy.cache.delete(`GET:/assets/${enc(fileId)}`);
351
425
  return res;
352
426
  }
@@ -356,12 +430,9 @@ export class AssetsApi {
356
430
  fileId: string,
357
431
  visibility: FileVisibility,
358
432
  ): Promise<{ file: { id: string; visibility: FileVisibility; updatedAt: string } }> {
359
- const res = await this.ctx.request<{ file: { id: string; visibility: FileVisibility; updatedAt: string } }>(
360
- 'PATCH',
361
- `/assets/${enc(fileId)}/visibility`,
362
- { visibility },
363
- { cache: false },
364
- );
433
+ const res = await this.ctx.request<{
434
+ file: { id: string; visibility: FileVisibility; updatedAt: string };
435
+ }>('PATCH', `/assets/${enc(fileId)}/visibility`, { visibility }, { cache: false });
365
436
  // Visibility changes the record AND the resolved URL (CDN vs signed).
366
437
  this.evict(fileId);
367
438
  return res;
@@ -369,7 +440,11 @@ export class AssetsApi {
369
440
 
370
441
  // ── Internals ────────────────────────────────────────────────────────────
371
442
 
372
- private async resolveUrl(fileId: string, variant?: string, expiresIn?: number): Promise<string | undefined> {
443
+ private async resolveUrl(
444
+ fileId: string,
445
+ variant?: string,
446
+ expiresIn?: number,
447
+ ): Promise<string | undefined> {
373
448
  const params: Record<string, string | number> = {};
374
449
  if (variant) params.variant = variant;
375
450
  if (expiresIn) params.expiresIn = expiresIn;
@@ -397,7 +472,10 @@ export class AssetsApi {
397
472
 
398
473
  /** Drop the cached record and every cached URL variant of an asset, in one pass. */
399
474
  private evict(fileId: string): void {
400
- this.ctx.http.invalidateCache({ keys: [`GET:/assets/${enc(fileId)}`], prefixes: [`GET:/assets/${enc(fileId)}/url`] });
475
+ this.ctx.http.invalidateCache({
476
+ keys: [`GET:/assets/${enc(fileId)}`],
477
+ prefixes: [`GET:/assets/${enc(fileId)}/url`],
478
+ });
401
479
  }
402
480
  }
403
481
 
@@ -418,7 +496,11 @@ function dedupeFileAccessRequests(
418
496
  const key = `${req.fileId}\u0000${req.variant ?? ''}`;
419
497
  if (seen.has(key)) continue;
420
498
  seen.add(key);
421
- out.push(req.variant === undefined ? { fileId: req.fileId } : { fileId: req.fileId, variant: req.variant });
499
+ out.push(
500
+ req.variant === undefined
501
+ ? { fileId: req.fileId }
502
+ : { fileId: req.fileId, variant: req.variant },
503
+ );
422
504
  }
423
505
  return out;
424
506
  }