@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.
- package/README.md +1 -1
- package/dist/cjs/HttpService.js +63 -19
- package/dist/cjs/api/accounts.js +10 -3
- package/dist/cjs/api/agency.js +3 -1
- package/dist/cjs/api/apps.js +15 -4
- package/dist/cjs/api/assets.js +49 -12
- package/dist/cjs/api/auth.js +37 -11
- package/dist/cjs/api/billing.js +24 -7
- package/dist/cjs/api/civic.js +14 -4
- package/dist/cjs/api/follows.js +9 -2
- package/dist/cjs/api/identity.js +31 -9
- package/dist/cjs/api/nodes.js +3 -1
- package/dist/cjs/api/privacy.js +8 -2
- package/dist/cjs/api/session.js +15 -4
- package/dist/cjs/api/store.js +15 -5
- package/dist/cjs/api/topics.js +10 -3
- package/dist/cjs/api/users.js +16 -4
- package/dist/cjs/boot/sessionColdBoot.js +40 -13
- package/dist/cjs/constants/version.js +6 -6
- package/dist/cjs/crypto/identityMarker.js +3 -1
- package/dist/cjs/crypto/identityProof.js +6 -1
- package/dist/cjs/crypto/keyManager.js +87 -32
- package/dist/cjs/crypto/recoveryPhrase.js +2 -2
- package/dist/cjs/crypto/signatureService.js +3 -4
- package/dist/cjs/i18n/index.js +16 -3
- package/dist/cjs/i18n/locales/ar-SA.js +366 -366
- package/dist/cjs/i18n/locales/ca-ES.js +366 -366
- package/dist/cjs/i18n/locales/de-DE.js +366 -366
- package/dist/cjs/i18n/locales/en-US.js +1994 -1994
- package/dist/cjs/i18n/locales/es-ES.js +1994 -1994
- package/dist/cjs/i18n/locales/fr-FR.js +366 -366
- package/dist/cjs/i18n/locales/it-IT.js +366 -366
- package/dist/cjs/i18n/locales/ja-JP.js +366 -366
- package/dist/cjs/i18n/locales/ko-KR.js +366 -366
- package/dist/cjs/i18n/locales/pt-PT.js +366 -366
- package/dist/cjs/i18n/locales/zh-CN.js +366 -366
- package/dist/cjs/inference/OxyInferenceClient.js +12 -18
- package/dist/cjs/models/interfaces.js +11 -11
- package/dist/cjs/server/OxyServer.js +86 -28
- package/dist/cjs/server/agentAccount.js +6 -2
- package/dist/cjs/server/aliaMachineCredential.js +39 -14
- package/dist/cjs/server/auth.js +5 -4
- package/dist/cjs/server/capabilityTicket.js +5 -5
- package/dist/cjs/server/index.js +2 -1
- package/dist/cjs/server/liveCapabilityTicket.js +4 -1
- package/dist/cjs/server/middleware.js +61 -42
- package/dist/cjs/server/namespaces.js +28 -7
- package/dist/cjs/server/requesterAssertion.js +36 -30
- package/dist/cjs/server/serviceTokenLifetime.js +7 -4
- package/dist/cjs/server/traffic.js +53 -14
- package/dist/cjs/server/trafficNodeHttp.js +33 -8
- package/dist/cjs/server/workloadIdentity.client.js +4 -0
- package/dist/cjs/server/workloadIdentity.js +28 -1
- package/dist/cjs/session/SessionClient.js +54 -17
- package/dist/cjs/session/accountDelegationAccess.js +4 -6
- package/dist/cjs/session/accountDialogController.js +1 -1
- package/dist/cjs/session/authStateStore.js +18 -9
- package/dist/cjs/session/identityPin.js +6 -2
- package/dist/cjs/session/refresh.js +81 -23
- package/dist/cjs/session/sharedDeviceCredential.js +28 -15
- package/dist/cjs/shared/utils/errorUtils.js +1 -1
- package/dist/cjs/shared/utils/networkUtils.js +1 -1
- package/dist/cjs/shared/utils/themeUtils.js +1 -1
- package/dist/cjs/utils/accountCacheSweep.js +3 -1
- package/dist/cjs/utils/accountUtils.js +1 -3
- package/dist/cjs/utils/asyncUtils.js +1 -1
- package/dist/cjs/utils/authHelpers.js +2 -1
- package/dist/cjs/utils/avatarUtils.js +4 -2
- package/dist/cjs/utils/cache.js +1 -1
- package/dist/cjs/utils/cacheKey.js +3 -1
- package/dist/cjs/utils/deviceManager.js +4 -4
- package/dist/cjs/utils/errorUtils.js +6 -4
- package/dist/cjs/utils/languageUtils.js +404 -57
- package/dist/cjs/utils/profileLinks.js +1 -3
- package/dist/cjs/utils/requestUtils.js +7 -1
- package/dist/cjs/utils/userIdentity.js +1 -1
- package/dist/cjs/utils/validationUtils.js +5 -6
- package/dist/esm/HttpService.js +64 -20
- package/dist/esm/api/accounts.js +11 -4
- package/dist/esm/api/agency.js +3 -1
- package/dist/esm/api/apps.js +15 -4
- package/dist/esm/api/assets.js +49 -12
- package/dist/esm/api/auth.js +37 -11
- package/dist/esm/api/billing.js +25 -8
- package/dist/esm/api/civic.js +14 -4
- package/dist/esm/api/follows.js +9 -2
- package/dist/esm/api/identity.js +31 -9
- package/dist/esm/api/nodes.js +3 -1
- package/dist/esm/api/privacy.js +8 -2
- package/dist/esm/api/session.js +15 -4
- package/dist/esm/api/store.js +15 -5
- package/dist/esm/api/topics.js +10 -3
- package/dist/esm/api/users.js +16 -4
- package/dist/esm/boot/sessionColdBoot.js +41 -14
- package/dist/esm/constants/version.js +6 -6
- package/dist/esm/crypto/identityMarker.js +3 -1
- package/dist/esm/crypto/identityProof.js +6 -1
- package/dist/esm/crypto/internal.js +1 -1
- package/dist/esm/crypto/keyManager.js +87 -32
- package/dist/esm/crypto/recoveryPhrase.js +2 -2
- package/dist/esm/crypto/signatureService.js +3 -4
- package/dist/esm/i18n/index.js +16 -3
- package/dist/esm/i18n/locales/ar-SA.js +366 -366
- package/dist/esm/i18n/locales/ca-ES.js +366 -366
- package/dist/esm/i18n/locales/de-DE.js +366 -366
- package/dist/esm/i18n/locales/en-US.js +1994 -1994
- package/dist/esm/i18n/locales/es-ES.js +1994 -1994
- package/dist/esm/i18n/locales/fr-FR.js +366 -366
- package/dist/esm/i18n/locales/it-IT.js +366 -366
- package/dist/esm/i18n/locales/ja-JP.js +366 -366
- package/dist/esm/i18n/locales/ko-KR.js +366 -366
- package/dist/esm/i18n/locales/pt-PT.js +366 -366
- package/dist/esm/i18n/locales/zh-CN.js +366 -366
- package/dist/esm/index.js +1 -1
- package/dist/esm/inference/OxyInferenceClient.js +13 -19
- package/dist/esm/models/interfaces.js +11 -11
- package/dist/esm/server/OxyServer.js +87 -29
- package/dist/esm/server/agentAccount.js +6 -2
- package/dist/esm/server/aliaMachineCredential.js +39 -14
- package/dist/esm/server/auth.js +6 -5
- package/dist/esm/server/capabilityTicket.js +6 -6
- package/dist/esm/server/index.js +5 -5
- package/dist/esm/server/liveCapabilityTicket.js +6 -3
- package/dist/esm/server/middleware.js +62 -43
- package/dist/esm/server/namespaces.js +31 -10
- package/dist/esm/server/requesterAssertion.js +36 -30
- package/dist/esm/server/serviceTokenLifetime.js +7 -4
- package/dist/esm/server/traffic.js +55 -16
- package/dist/esm/server/trafficNodeHttp.js +34 -9
- package/dist/esm/server/userInvalidation.js +1 -1
- package/dist/esm/server/workloadIdentity.client.js +3 -0
- package/dist/esm/server/workloadIdentity.js +27 -1
- package/dist/esm/session/SessionClient.js +54 -17
- package/dist/esm/session/accountDelegationAccess.js +5 -7
- package/dist/esm/session/accountDialogController.js +1 -1
- package/dist/esm/session/authStateStore.js +18 -9
- package/dist/esm/session/identityPin.js +6 -2
- package/dist/esm/session/refresh.js +82 -24
- package/dist/esm/session/sharedDeviceCredential.js +28 -15
- package/dist/esm/shared/utils/errorUtils.js +1 -1
- package/dist/esm/shared/utils/networkUtils.js +1 -1
- package/dist/esm/shared/utils/themeUtils.js +1 -1
- package/dist/esm/utils/accountCacheSweep.js +3 -1
- package/dist/esm/utils/accountUtils.js +1 -3
- package/dist/esm/utils/asyncUtils.js +1 -1
- package/dist/esm/utils/authHelpers.js +2 -1
- package/dist/esm/utils/avatarUtils.js +4 -2
- package/dist/esm/utils/cache.js +1 -1
- package/dist/esm/utils/cacheKey.js +3 -1
- package/dist/esm/utils/deviceManager.js +4 -4
- package/dist/esm/utils/errorUtils.js +6 -4
- package/dist/esm/utils/languageUtils.js +404 -57
- package/dist/esm/utils/profileLinks.js +1 -3
- package/dist/esm/utils/requestUtils.js +7 -1
- package/dist/esm/utils/userIdentity.js +1 -1
- package/dist/esm/utils/validationUtils.js +5 -6
- package/dist/types/HttpService.d.ts +1 -1
- package/dist/types/api/accounts.d.ts +1 -1
- package/dist/types/api/apps.d.ts +4 -4
- package/dist/types/api/assets.d.ts +2 -0
- package/dist/types/api/auth.d.ts +8 -3
- package/dist/types/crypto/internal.d.ts +1 -1
- package/dist/types/index.d.ts +4 -4
- package/dist/types/server/index.d.ts +6 -6
- package/dist/types/server/requesterAssertion.d.ts +2 -2
- package/dist/types/server/workloadIdentity.client.d.ts +5 -1
- package/dist/types/server/workloadIdentity.d.ts +26 -0
- package/dist/types/session/accountDelegationAccess.d.ts +1 -1
- package/dist/types/session/index.d.ts +1 -1
- package/dist/types/utils/userIdentity.d.ts +1 -1
- package/dist/types/utils/validationUtils.d.ts +4 -5
- package/package.json +2 -3
- package/src/HttpService.ts +183 -53
- package/src/OxyServices.errors.ts +7 -3
- package/src/OxyServices.ts +6 -2
- package/src/api/accounts.ts +76 -26
- package/src/api/agency.ts +24 -9
- package/src/api/appData.ts +12 -2
- package/src/api/apps.ts +81 -31
- package/src/api/assets.ts +122 -40
- package/src/api/auth.ts +154 -79
- package/src/api/billing.ts +112 -65
- package/src/api/civic.ts +61 -19
- package/src/api/contacts.ts +4 -1
- package/src/api/devices.ts +54 -21
- package/src/api/follows.ts +88 -31
- package/src/api/identity.ts +101 -33
- package/src/api/linkedAccounts.ts +26 -8
- package/src/api/nodes.ts +18 -6
- package/src/api/notifications.ts +26 -6
- package/src/api/privacy.ts +42 -8
- package/src/api/reputation.ts +18 -7
- package/src/api/session.ts +23 -5
- package/src/api/store.ts +81 -31
- package/src/api/topics.ts +18 -6
- package/src/api/users.ts +98 -35
- package/src/boot/sessionColdBoot.ts +60 -19
- package/src/civic/payloads.ts +1 -4
- package/src/client/context.ts +6 -1
- package/src/constants/version.ts +7 -6
- package/src/crypto/aead.ts +1 -5
- package/src/crypto/ecdh.ts +1 -4
- package/src/crypto/identityDerivations.ts +5 -1
- package/src/crypto/identityMarker.ts +3 -1
- package/src/crypto/identityProof.ts +6 -1
- package/src/crypto/index.ts +11 -11
- package/src/crypto/internal.ts +6 -1
- package/src/crypto/keyManager.ts +348 -98
- package/src/crypto/recoveryPhrase.ts +14 -9
- package/src/crypto/registrationPow.ts +1 -1
- package/src/crypto/signatureService.ts +14 -6
- package/src/i18n/accountCategoryLabels.ts +1 -4
- package/src/i18n/accountRoleLabels.ts +1 -4
- package/src/i18n/index.ts +25 -7
- package/src/i18n/locales/ar-SA.ts +375 -366
- package/src/i18n/locales/ca-ES.ts +382 -366
- package/src/i18n/locales/de-DE.ts +387 -366
- package/src/i18n/locales/en-US.ts +2034 -1994
- package/src/i18n/locales/es-ES.ts +2043 -1994
- package/src/i18n/locales/fr-FR.ts +387 -366
- package/src/i18n/locales/it-IT.ts +380 -366
- package/src/i18n/locales/ja-JP.ts +380 -366
- package/src/i18n/locales/ko-KR.ts +377 -366
- package/src/i18n/locales/pt-PT.ts +383 -366
- package/src/i18n/locales/zh-CN.ts +373 -366
- package/src/i18n/trustTierLabels.ts +1 -4
- package/src/index.ts +371 -349
- package/src/inference/OxyInferenceClient.ts +784 -780
- package/src/models/interfaces.ts +30 -27
- package/src/server/OxyServer.ts +227 -68
- package/src/server/agentAccount.ts +8 -2
- package/src/server/aliaMachineCredential.ts +57 -16
- package/src/server/auth.ts +9 -5
- package/src/server/capabilityTicket.ts +30 -21
- package/src/server/index.ts +29 -6
- package/src/server/liveCapabilityTicket.ts +31 -9
- package/src/server/middleware.ts +212 -121
- package/src/server/namespaces.ts +247 -94
- package/src/server/rateLimit.ts +2 -4
- package/src/server/requesterAssertion.ts +93 -54
- package/src/server/serviceTokenLifetime.ts +9 -4
- package/src/server/traffic.ts +117 -23
- package/src/server/trafficNodeHttp.ts +61 -14
- package/src/server/userInvalidation.ts +1 -4
- package/src/server/workloadIdentity.client.ts +12 -1
- package/src/server/workloadIdentity.ts +52 -5
- package/src/session/SessionClient.ts +170 -49
- package/src/session/accountDelegationAccess.ts +24 -31
- package/src/session/accountDialogController.ts +59 -14
- package/src/session/accountSwitchTargets.ts +10 -15
- package/src/session/authStateStore.ts +121 -81
- package/src/session/deviceDirectory.ts +1 -3
- package/src/session/identityPin.ts +10 -11
- package/src/session/identitySession.ts +3 -1
- package/src/session/index.ts +87 -82
- package/src/session/refresh.ts +138 -44
- package/src/session/sessionClientHost.ts +1 -3
- package/src/session/sharedDeviceCredential.ts +35 -14
- package/src/session/socketLoader.ts +9 -2
- package/src/shared/utils/errorUtils.ts +5 -2
- package/src/shared/utils/networkUtils.ts +5 -8
- package/src/shared/utils/themeUtils.ts +2 -6
- package/src/types/buffer.d.ts +66 -21
- package/src/types/expo-secure-store.d.ts +5 -1
- package/src/utils/accountCacheSweep.ts +4 -5
- package/src/utils/accountUtils.ts +107 -108
- package/src/utils/apiUtils.ts +3 -3
- package/src/utils/asyncUtils.ts +2 -2
- package/src/utils/authHelpers.ts +10 -5
- package/src/utils/avatarUtils.ts +11 -6
- package/src/utils/cache.ts +9 -10
- package/src/utils/cacheKey.ts +5 -1
- package/src/utils/coldBoot.ts +1 -3
- package/src/utils/commonsDelivery.ts +1 -4
- package/src/utils/deviceManager.ts +15 -14
- package/src/utils/errorUtils.ts +68 -86
- package/src/utils/languageUtils.ts +407 -58
- package/src/utils/oauthPkce.ts +1 -4
- package/src/utils/platform.ts +0 -1
- package/src/utils/profileLinks.ts +2 -5
- package/src/utils/requestUtils.ts +18 -14
- package/src/utils/sessionUtils.ts +34 -33
- package/src/utils/userHandle.ts +3 -1
- package/src/utils/userIdentity.ts +1 -1
- 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<
|
|
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 (
|
|
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(),{
|
|
117
|
-
|
|
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(
|
|
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 (
|
|
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 =
|
|
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(
|
|
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 }>(
|
|
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 = {
|
|
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(
|
|
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(
|
|
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 } = {
|
|
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 }>(
|
|
195
|
-
|
|
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 }>(
|
|
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, {
|
|
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(
|
|
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, {
|
|
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, {
|
|
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, {
|
|
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(
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
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<{
|
|
360
|
-
|
|
361
|
-
|
|
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(
|
|
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({
|
|
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(
|
|
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
|
}
|