@oxyhq/core 1.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.
- package/README.md +50 -0
- package/dist/cjs/AuthManager.js +361 -0
- package/dist/cjs/CrossDomainAuth.js +258 -0
- package/dist/cjs/HttpService.js +618 -0
- package/dist/cjs/OxyServices.base.js +263 -0
- package/dist/cjs/OxyServices.errors.js +22 -0
- package/dist/cjs/OxyServices.js +63 -0
- package/dist/cjs/constants/version.js +16 -0
- package/dist/cjs/crypto/index.js +20 -0
- package/dist/cjs/crypto/keyManager.js +887 -0
- package/dist/cjs/crypto/polyfill.js +64 -0
- package/dist/cjs/crypto/recoveryPhrase.js +169 -0
- package/dist/cjs/crypto/signatureService.js +296 -0
- package/dist/cjs/i18n/index.js +73 -0
- package/dist/cjs/i18n/locales/ar-SA.json +120 -0
- package/dist/cjs/i18n/locales/ca-ES.json +120 -0
- package/dist/cjs/i18n/locales/de-DE.json +120 -0
- package/dist/cjs/i18n/locales/en-US.json +956 -0
- package/dist/cjs/i18n/locales/es-ES.json +944 -0
- package/dist/cjs/i18n/locales/fr-FR.json +120 -0
- package/dist/cjs/i18n/locales/it-IT.json +120 -0
- package/dist/cjs/i18n/locales/ja-JP.json +119 -0
- package/dist/cjs/i18n/locales/ko-KR.json +120 -0
- package/dist/cjs/i18n/locales/locales/ar-SA.json +120 -0
- package/dist/cjs/i18n/locales/locales/ca-ES.json +120 -0
- package/dist/cjs/i18n/locales/locales/de-DE.json +120 -0
- package/dist/cjs/i18n/locales/locales/en-US.json +956 -0
- package/dist/cjs/i18n/locales/locales/es-ES.json +944 -0
- package/dist/cjs/i18n/locales/locales/fr-FR.json +120 -0
- package/dist/cjs/i18n/locales/locales/it-IT.json +120 -0
- package/dist/cjs/i18n/locales/locales/ja-JP.json +119 -0
- package/dist/cjs/i18n/locales/locales/ko-KR.json +120 -0
- package/dist/cjs/i18n/locales/locales/pt-PT.json +120 -0
- package/dist/cjs/i18n/locales/locales/zh-CN.json +120 -0
- package/dist/cjs/i18n/locales/pt-PT.json +120 -0
- package/dist/cjs/i18n/locales/zh-CN.json +120 -0
- package/dist/cjs/index.js +153 -0
- package/dist/cjs/mixins/OxyServices.analytics.js +49 -0
- package/dist/cjs/mixins/OxyServices.assets.js +380 -0
- package/dist/cjs/mixins/OxyServices.auth.js +259 -0
- package/dist/cjs/mixins/OxyServices.developer.js +97 -0
- package/dist/cjs/mixins/OxyServices.devices.js +116 -0
- package/dist/cjs/mixins/OxyServices.features.js +309 -0
- package/dist/cjs/mixins/OxyServices.fedcm.js +435 -0
- package/dist/cjs/mixins/OxyServices.karma.js +108 -0
- package/dist/cjs/mixins/OxyServices.language.js +154 -0
- package/dist/cjs/mixins/OxyServices.location.js +43 -0
- package/dist/cjs/mixins/OxyServices.payment.js +158 -0
- package/dist/cjs/mixins/OxyServices.popup.js +371 -0
- package/dist/cjs/mixins/OxyServices.privacy.js +162 -0
- package/dist/cjs/mixins/OxyServices.redirect.js +345 -0
- package/dist/cjs/mixins/OxyServices.security.js +81 -0
- package/dist/cjs/mixins/OxyServices.user.js +355 -0
- package/dist/cjs/mixins/OxyServices.utility.js +156 -0
- package/dist/cjs/mixins/index.js +79 -0
- package/dist/cjs/mixins/mixinHelpers.js +53 -0
- package/dist/cjs/models/interfaces.js +20 -0
- package/dist/cjs/models/session.js +2 -0
- package/dist/cjs/shared/index.js +70 -0
- package/dist/cjs/shared/utils/colorUtils.js +153 -0
- package/dist/cjs/shared/utils/debugUtils.js +73 -0
- package/dist/cjs/shared/utils/errorUtils.js +183 -0
- package/dist/cjs/shared/utils/index.js +49 -0
- package/dist/cjs/shared/utils/networkUtils.js +183 -0
- package/dist/cjs/shared/utils/themeUtils.js +106 -0
- package/dist/cjs/utils/apiUtils.js +61 -0
- package/dist/cjs/utils/asyncUtils.js +194 -0
- package/dist/cjs/utils/cache.js +226 -0
- package/dist/cjs/utils/deviceManager.js +205 -0
- package/dist/cjs/utils/errorUtils.js +154 -0
- package/dist/cjs/utils/index.js +26 -0
- package/dist/cjs/utils/languageUtils.js +165 -0
- package/dist/cjs/utils/loggerUtils.js +126 -0
- package/dist/cjs/utils/platform.js +144 -0
- package/dist/cjs/utils/requestUtils.js +209 -0
- package/dist/cjs/utils/sessionUtils.js +181 -0
- package/dist/cjs/utils/validationUtils.js +173 -0
- package/dist/esm/AuthManager.js +356 -0
- package/dist/esm/CrossDomainAuth.js +253 -0
- package/dist/esm/HttpService.js +614 -0
- package/dist/esm/OxyServices.base.js +259 -0
- package/dist/esm/OxyServices.errors.js +17 -0
- package/dist/esm/OxyServices.js +59 -0
- package/dist/esm/constants/version.js +13 -0
- package/dist/esm/crypto/index.js +13 -0
- package/dist/esm/crypto/keyManager.js +850 -0
- package/dist/esm/crypto/polyfill.js +61 -0
- package/dist/esm/crypto/recoveryPhrase.js +132 -0
- package/dist/esm/crypto/signatureService.js +259 -0
- package/dist/esm/i18n/index.js +69 -0
- package/dist/esm/i18n/locales/ar-SA.json +120 -0
- package/dist/esm/i18n/locales/ca-ES.json +120 -0
- package/dist/esm/i18n/locales/de-DE.json +120 -0
- package/dist/esm/i18n/locales/en-US.json +956 -0
- package/dist/esm/i18n/locales/es-ES.json +944 -0
- package/dist/esm/i18n/locales/fr-FR.json +120 -0
- package/dist/esm/i18n/locales/it-IT.json +120 -0
- package/dist/esm/i18n/locales/ja-JP.json +119 -0
- package/dist/esm/i18n/locales/ko-KR.json +120 -0
- package/dist/esm/i18n/locales/locales/ar-SA.json +120 -0
- package/dist/esm/i18n/locales/locales/ca-ES.json +120 -0
- package/dist/esm/i18n/locales/locales/de-DE.json +120 -0
- package/dist/esm/i18n/locales/locales/en-US.json +956 -0
- package/dist/esm/i18n/locales/locales/es-ES.json +944 -0
- package/dist/esm/i18n/locales/locales/fr-FR.json +120 -0
- package/dist/esm/i18n/locales/locales/it-IT.json +120 -0
- package/dist/esm/i18n/locales/locales/ja-JP.json +119 -0
- package/dist/esm/i18n/locales/locales/ko-KR.json +120 -0
- package/dist/esm/i18n/locales/locales/pt-PT.json +120 -0
- package/dist/esm/i18n/locales/locales/zh-CN.json +120 -0
- package/dist/esm/i18n/locales/pt-PT.json +120 -0
- package/dist/esm/i18n/locales/zh-CN.json +120 -0
- package/dist/esm/index.js +55 -0
- package/dist/esm/mixins/OxyServices.analytics.js +46 -0
- package/dist/esm/mixins/OxyServices.assets.js +377 -0
- package/dist/esm/mixins/OxyServices.auth.js +256 -0
- package/dist/esm/mixins/OxyServices.developer.js +94 -0
- package/dist/esm/mixins/OxyServices.devices.js +113 -0
- package/dist/esm/mixins/OxyServices.features.js +306 -0
- package/dist/esm/mixins/OxyServices.fedcm.js +433 -0
- package/dist/esm/mixins/OxyServices.karma.js +105 -0
- package/dist/esm/mixins/OxyServices.language.js +118 -0
- package/dist/esm/mixins/OxyServices.location.js +40 -0
- package/dist/esm/mixins/OxyServices.payment.js +155 -0
- package/dist/esm/mixins/OxyServices.popup.js +369 -0
- package/dist/esm/mixins/OxyServices.privacy.js +159 -0
- package/dist/esm/mixins/OxyServices.redirect.js +343 -0
- package/dist/esm/mixins/OxyServices.security.js +78 -0
- package/dist/esm/mixins/OxyServices.user.js +352 -0
- package/dist/esm/mixins/OxyServices.utility.js +153 -0
- package/dist/esm/mixins/index.js +76 -0
- package/dist/esm/mixins/mixinHelpers.js +48 -0
- package/dist/esm/models/interfaces.js +17 -0
- package/dist/esm/models/session.js +1 -0
- package/dist/esm/shared/index.js +31 -0
- package/dist/esm/shared/utils/colorUtils.js +143 -0
- package/dist/esm/shared/utils/debugUtils.js +65 -0
- package/dist/esm/shared/utils/errorUtils.js +170 -0
- package/dist/esm/shared/utils/index.js +15 -0
- package/dist/esm/shared/utils/networkUtils.js +173 -0
- package/dist/esm/shared/utils/themeUtils.js +98 -0
- package/dist/esm/utils/apiUtils.js +55 -0
- package/dist/esm/utils/asyncUtils.js +179 -0
- package/dist/esm/utils/cache.js +218 -0
- package/dist/esm/utils/deviceManager.js +168 -0
- package/dist/esm/utils/errorUtils.js +146 -0
- package/dist/esm/utils/index.js +7 -0
- package/dist/esm/utils/languageUtils.js +158 -0
- package/dist/esm/utils/loggerUtils.js +115 -0
- package/dist/esm/utils/platform.js +102 -0
- package/dist/esm/utils/requestUtils.js +203 -0
- package/dist/esm/utils/sessionUtils.js +171 -0
- package/dist/esm/utils/validationUtils.js +153 -0
- package/dist/types/AuthManager.d.ts +143 -0
- package/dist/types/CrossDomainAuth.d.ts +160 -0
- package/dist/types/HttpService.d.ts +163 -0
- package/dist/types/OxyServices.base.d.ts +126 -0
- package/dist/types/OxyServices.d.ts +81 -0
- package/dist/types/OxyServices.errors.d.ts +11 -0
- package/dist/types/constants/version.d.ts +13 -0
- package/dist/types/crypto/index.d.ts +11 -0
- package/dist/types/crypto/keyManager.d.ts +189 -0
- package/dist/types/crypto/polyfill.d.ts +11 -0
- package/dist/types/crypto/recoveryPhrase.d.ts +58 -0
- package/dist/types/crypto/signatureService.d.ts +86 -0
- package/dist/types/i18n/index.d.ts +3 -0
- package/dist/types/index.d.ts +50 -0
- package/dist/types/mixins/OxyServices.analytics.d.ts +66 -0
- package/dist/types/mixins/OxyServices.assets.d.ts +135 -0
- package/dist/types/mixins/OxyServices.auth.d.ts +186 -0
- package/dist/types/mixins/OxyServices.developer.d.ts +99 -0
- package/dist/types/mixins/OxyServices.devices.d.ts +96 -0
- package/dist/types/mixins/OxyServices.features.d.ts +228 -0
- package/dist/types/mixins/OxyServices.fedcm.d.ts +200 -0
- package/dist/types/mixins/OxyServices.karma.d.ts +85 -0
- package/dist/types/mixins/OxyServices.language.d.ts +81 -0
- package/dist/types/mixins/OxyServices.location.d.ts +64 -0
- package/dist/types/mixins/OxyServices.payment.d.ts +111 -0
- package/dist/types/mixins/OxyServices.popup.d.ts +205 -0
- package/dist/types/mixins/OxyServices.privacy.d.ts +122 -0
- package/dist/types/mixins/OxyServices.redirect.d.ts +245 -0
- package/dist/types/mixins/OxyServices.security.d.ts +78 -0
- package/dist/types/mixins/OxyServices.user.d.ts +182 -0
- package/dist/types/mixins/OxyServices.utility.d.ts +93 -0
- package/dist/types/mixins/index.d.ts +30 -0
- package/dist/types/mixins/mixinHelpers.d.ts +31 -0
- package/dist/types/models/interfaces.d.ts +415 -0
- package/dist/types/models/session.d.ts +27 -0
- package/dist/types/shared/index.d.ts +28 -0
- package/dist/types/shared/utils/colorUtils.d.ts +104 -0
- package/dist/types/shared/utils/debugUtils.d.ts +48 -0
- package/dist/types/shared/utils/errorUtils.d.ts +97 -0
- package/dist/types/shared/utils/index.d.ts +13 -0
- package/dist/types/shared/utils/networkUtils.d.ts +139 -0
- package/dist/types/shared/utils/themeUtils.d.ts +90 -0
- package/dist/types/utils/apiUtils.d.ts +53 -0
- package/dist/types/utils/asyncUtils.d.ts +58 -0
- package/dist/types/utils/cache.d.ts +127 -0
- package/dist/types/utils/deviceManager.d.ts +65 -0
- package/dist/types/utils/errorUtils.d.ts +46 -0
- package/dist/types/utils/index.d.ts +6 -0
- package/dist/types/utils/languageUtils.d.ts +37 -0
- package/dist/types/utils/loggerUtils.d.ts +48 -0
- package/dist/types/utils/platform.d.ts +40 -0
- package/dist/types/utils/requestUtils.d.ts +123 -0
- package/dist/types/utils/sessionUtils.d.ts +54 -0
- package/dist/types/utils/validationUtils.d.ts +85 -0
- package/package.json +84 -0
- package/src/AuthManager.ts +436 -0
- package/src/CrossDomainAuth.ts +307 -0
- package/src/HttpService.ts +752 -0
- package/src/OxyServices.base.ts +334 -0
- package/src/OxyServices.errors.ts +26 -0
- package/src/OxyServices.ts +129 -0
- package/src/constants/version.ts +15 -0
- package/src/crypto/index.ts +25 -0
- package/src/crypto/keyManager.ts +962 -0
- package/src/crypto/polyfill.ts +70 -0
- package/src/crypto/recoveryPhrase.ts +166 -0
- package/src/crypto/signatureService.ts +323 -0
- package/src/i18n/index.ts +75 -0
- package/src/i18n/locales/ar-SA.json +120 -0
- package/src/i18n/locales/ca-ES.json +120 -0
- package/src/i18n/locales/de-DE.json +120 -0
- package/src/i18n/locales/en-US.json +956 -0
- package/src/i18n/locales/es-ES.json +944 -0
- package/src/i18n/locales/fr-FR.json +120 -0
- package/src/i18n/locales/it-IT.json +120 -0
- package/src/i18n/locales/ja-JP.json +119 -0
- package/src/i18n/locales/ko-KR.json +120 -0
- package/src/i18n/locales/pt-PT.json +120 -0
- package/src/i18n/locales/zh-CN.json +120 -0
- package/src/index.ts +153 -0
- package/src/mixins/OxyServices.analytics.ts +53 -0
- package/src/mixins/OxyServices.assets.ts +412 -0
- package/src/mixins/OxyServices.auth.ts +358 -0
- package/src/mixins/OxyServices.developer.ts +114 -0
- package/src/mixins/OxyServices.devices.ts +119 -0
- package/src/mixins/OxyServices.features.ts +428 -0
- package/src/mixins/OxyServices.fedcm.ts +494 -0
- package/src/mixins/OxyServices.karma.ts +111 -0
- package/src/mixins/OxyServices.language.ts +127 -0
- package/src/mixins/OxyServices.location.ts +46 -0
- package/src/mixins/OxyServices.payment.ts +163 -0
- package/src/mixins/OxyServices.popup.ts +443 -0
- package/src/mixins/OxyServices.privacy.ts +182 -0
- package/src/mixins/OxyServices.redirect.ts +397 -0
- package/src/mixins/OxyServices.security.ts +103 -0
- package/src/mixins/OxyServices.user.ts +392 -0
- package/src/mixins/OxyServices.utility.ts +191 -0
- package/src/mixins/index.ts +91 -0
- package/src/mixins/mixinHelpers.ts +69 -0
- package/src/models/interfaces.ts +511 -0
- package/src/models/session.ts +30 -0
- package/src/shared/index.ts +82 -0
- package/src/shared/utils/colorUtils.ts +155 -0
- package/src/shared/utils/debugUtils.ts +73 -0
- package/src/shared/utils/errorUtils.ts +181 -0
- package/src/shared/utils/index.ts +59 -0
- package/src/shared/utils/networkUtils.ts +248 -0
- package/src/shared/utils/themeUtils.ts +115 -0
- package/src/types/bip39.d.ts +32 -0
- package/src/types/buffer.d.ts +97 -0
- package/src/types/color.d.ts +20 -0
- package/src/types/elliptic.d.ts +62 -0
- package/src/utils/apiUtils.ts +88 -0
- package/src/utils/asyncUtils.ts +252 -0
- package/src/utils/cache.ts +264 -0
- package/src/utils/deviceManager.ts +198 -0
- package/src/utils/errorUtils.ts +216 -0
- package/src/utils/index.ts +21 -0
- package/src/utils/languageUtils.ts +174 -0
- package/src/utils/loggerUtils.ts +153 -0
- package/src/utils/platform.ts +117 -0
- package/src/utils/requestUtils.ts +237 -0
- package/src/utils/sessionUtils.ts +206 -0
- package/src/utils/validationUtils.ts +174 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import type { AccountStorageUsageResponse, AssetUrlResponse, AssetVariant } from '../models/interfaces';
|
|
2
|
+
import type { OxyServicesBase } from '../OxyServices.base';
|
|
3
|
+
|
|
4
|
+
export function OxyServicesAssetsMixin<T extends typeof OxyServicesBase>(Base: T) {
|
|
5
|
+
return class extends Base {
|
|
6
|
+
constructor(...args: any[]) {
|
|
7
|
+
super(...(args as [any]));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Delete file
|
|
12
|
+
*/
|
|
13
|
+
async deleteFile(fileId: string): Promise<any> {
|
|
14
|
+
try {
|
|
15
|
+
return await this.makeRequest('DELETE', `/api/assets/${encodeURIComponent(fileId)}`, undefined, { cache: false });
|
|
16
|
+
} catch (error) {
|
|
17
|
+
throw this.handleError(error);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get file download URL (synchronous - uses stream endpoint for images to avoid ORB blocking)
|
|
23
|
+
*/
|
|
24
|
+
getFileDownloadUrl(fileId: string, variant?: string, expiresIn?: number): string {
|
|
25
|
+
const base = this.getBaseURL();
|
|
26
|
+
const params = new URLSearchParams();
|
|
27
|
+
if (variant) params.set('variant', variant);
|
|
28
|
+
if (expiresIn) params.set('expiresIn', String(expiresIn));
|
|
29
|
+
params.set('fallback', 'placeholderVisible');
|
|
30
|
+
const token = this.getClient().getAccessToken();
|
|
31
|
+
if (token) params.set('token', token);
|
|
32
|
+
|
|
33
|
+
const qs = params.toString();
|
|
34
|
+
return `${base}/api/assets/${encodeURIComponent(fileId)}/stream${qs ? `?${qs}` : ''}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get file download URL asynchronously (returns signed URL directly from CDN)
|
|
39
|
+
*/
|
|
40
|
+
async getFileDownloadUrlAsync(fileId: string, variant?: string, expiresIn?: number): Promise<string> {
|
|
41
|
+
try {
|
|
42
|
+
const url = await this.fetchAssetDownloadUrl(
|
|
43
|
+
fileId,
|
|
44
|
+
variant,
|
|
45
|
+
this.getAssetUrlCacheTTL(expiresIn),
|
|
46
|
+
expiresIn
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
return url || this.getFileDownloadUrl(fileId, variant, expiresIn);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
return this.getFileDownloadUrl(fileId, variant, expiresIn);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* List user files
|
|
57
|
+
*/
|
|
58
|
+
async listUserFiles(limit?: number, offset?: number): Promise<{ files: any[]; total: number; hasMore: boolean }> {
|
|
59
|
+
try {
|
|
60
|
+
const paramsObj: any = {};
|
|
61
|
+
if (limit) paramsObj.limit = limit;
|
|
62
|
+
if (offset) paramsObj.offset = offset;
|
|
63
|
+
return await this.makeRequest('GET', '/api/assets', paramsObj, {
|
|
64
|
+
cache: false,
|
|
65
|
+
});
|
|
66
|
+
} catch (error) {
|
|
67
|
+
throw this.handleError(error);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get account storage usage (server-side usage aggregated from assets)
|
|
73
|
+
*/
|
|
74
|
+
async getAccountStorageUsage(): Promise<AccountStorageUsageResponse> {
|
|
75
|
+
try {
|
|
76
|
+
return await this.makeRequest<AccountStorageUsageResponse>('GET', '/api/storage/usage', undefined, {
|
|
77
|
+
cache: false,
|
|
78
|
+
});
|
|
79
|
+
} catch (error) {
|
|
80
|
+
throw this.handleError(error);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get file content as text
|
|
86
|
+
*/
|
|
87
|
+
async getFileContentAsText(fileId: string, variant?: string): Promise<string> {
|
|
88
|
+
try {
|
|
89
|
+
const downloadUrl = await this.fetchAssetDownloadUrl(
|
|
90
|
+
fileId,
|
|
91
|
+
variant,
|
|
92
|
+
this.getAssetUrlCacheTTL()
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
if (!downloadUrl) {
|
|
96
|
+
throw new Error('No download URL returned for asset');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return await this.fetchAssetContent(downloadUrl, 'text');
|
|
100
|
+
} catch (error) {
|
|
101
|
+
throw this.handleError(error);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Get file content as blob
|
|
107
|
+
*/
|
|
108
|
+
async getFileContentAsBlob(fileId: string, variant?: string): Promise<Blob> {
|
|
109
|
+
try {
|
|
110
|
+
const downloadUrl = await this.fetchAssetDownloadUrl(
|
|
111
|
+
fileId,
|
|
112
|
+
variant,
|
|
113
|
+
this.getAssetUrlCacheTTL()
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
if (!downloadUrl) {
|
|
117
|
+
throw new Error('No download URL returned for asset');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return await this.fetchAssetContent(downloadUrl, 'blob');
|
|
121
|
+
} catch (error) {
|
|
122
|
+
throw this.handleError(error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Get batch access to multiple files
|
|
128
|
+
*/
|
|
129
|
+
async getBatchFileAccess(fileIds: string[], context?: string): Promise<Record<string, any>> {
|
|
130
|
+
try {
|
|
131
|
+
return await this.makeRequest('POST', '/api/assets/batch-access', {
|
|
132
|
+
fileIds,
|
|
133
|
+
context
|
|
134
|
+
});
|
|
135
|
+
} catch (error) {
|
|
136
|
+
throw this.handleError(error);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Get download URLs for multiple files efficiently
|
|
142
|
+
*/
|
|
143
|
+
async getFileDownloadUrls(fileIds: string[], context?: string): Promise<Record<string, string>> {
|
|
144
|
+
const response: any = await this.getBatchFileAccess(fileIds, context);
|
|
145
|
+
const urls: Record<string, string> = {};
|
|
146
|
+
const results = response.results || {};
|
|
147
|
+
for (const [id, result] of Object.entries(results as Record<string, any>)) {
|
|
148
|
+
if (result.allowed && result.url) {
|
|
149
|
+
urls[id] = result.url;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return urls;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Upload raw file data
|
|
157
|
+
*/
|
|
158
|
+
async uploadRawFile(file: File | Blob, visibility?: 'private' | 'public' | 'unlisted', metadata?: Record<string, any>): Promise<any> {
|
|
159
|
+
return this.assetUpload(file as File, visibility, metadata);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Upload file using Central Asset Service
|
|
164
|
+
*/
|
|
165
|
+
async assetUpload(file: File, visibility?: 'private' | 'public' | 'unlisted', metadata?: Record<string, any>, onProgress?: (progress: number) => void): Promise<any> {
|
|
166
|
+
const fileName = file.name || 'unknown';
|
|
167
|
+
const fileSize = file.size;
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
const formData = new FormData();
|
|
171
|
+
// Convert File to Blob to avoid read-only 'name' property error in Expo 54
|
|
172
|
+
// This is a known issue in Expo SDK 52+ where FormData tries to set the read-only 'name' property
|
|
173
|
+
let fileBlob: Blob;
|
|
174
|
+
if (file instanceof Blob) {
|
|
175
|
+
// Already a Blob, use directly
|
|
176
|
+
fileBlob = file;
|
|
177
|
+
} else if (typeof (file as any).blob === 'function') {
|
|
178
|
+
// Use async blob() method if available (Expo 54+ recommended approach)
|
|
179
|
+
fileBlob = await (file as any).blob();
|
|
180
|
+
} else {
|
|
181
|
+
// Fallback: create Blob from File (works in all environments)
|
|
182
|
+
fileBlob = new Blob([file], { type: (file as any).type || 'application/octet-stream' });
|
|
183
|
+
}
|
|
184
|
+
formData.append('file', fileBlob, fileName);
|
|
185
|
+
if (visibility) {
|
|
186
|
+
formData.append('visibility', visibility);
|
|
187
|
+
}
|
|
188
|
+
if (metadata) {
|
|
189
|
+
formData.append('metadata', JSON.stringify(metadata));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const response = await this.getClient().request<{ file: any }>({
|
|
193
|
+
method: 'POST',
|
|
194
|
+
url: '/api/assets/upload',
|
|
195
|
+
data: formData,
|
|
196
|
+
cache: false,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
if (onProgress && response) {
|
|
200
|
+
onProgress(100);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return response;
|
|
204
|
+
} catch (error) {
|
|
205
|
+
console.error('File upload error:', error);
|
|
206
|
+
|
|
207
|
+
let errorMessage = 'File upload failed';
|
|
208
|
+
|
|
209
|
+
if (error instanceof Error) {
|
|
210
|
+
errorMessage = error.message || errorMessage;
|
|
211
|
+
} else if (error && typeof error === 'object') {
|
|
212
|
+
if ('message' in error) {
|
|
213
|
+
errorMessage = String((error as any).message) || errorMessage;
|
|
214
|
+
} else if ('error' in error && typeof (error as any).error === 'string') {
|
|
215
|
+
errorMessage = (error as any).error;
|
|
216
|
+
} else if ('data' in error && (error as any).data?.message) {
|
|
217
|
+
errorMessage = String((error as any).data.message);
|
|
218
|
+
}
|
|
219
|
+
} else if (error) {
|
|
220
|
+
errorMessage = String(error) || errorMessage;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const contextError = error as Error & { fileContext?: Record<string, unknown> };
|
|
224
|
+
if (!contextError.fileContext) {
|
|
225
|
+
contextError.fileContext = {
|
|
226
|
+
fileName,
|
|
227
|
+
fileSize,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (error instanceof Error && error.message) {
|
|
232
|
+
const handledError = this.handleError(contextError);
|
|
233
|
+
if (!handledError.message || handledError.message.trim() === 'An unexpected error occurred') {
|
|
234
|
+
handledError.message = errorMessage;
|
|
235
|
+
}
|
|
236
|
+
throw handledError;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const newError = new Error(errorMessage);
|
|
240
|
+
(newError as any).fileContext = contextError.fileContext;
|
|
241
|
+
throw this.handleError(newError);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Link asset to an entity
|
|
247
|
+
*/
|
|
248
|
+
async assetLink(fileId: string, app: string, entityType: string, entityId: string, visibility?: 'private' | 'public' | 'unlisted', webhookUrl?: string): Promise<any> {
|
|
249
|
+
try {
|
|
250
|
+
const body: any = { app, entityType, entityId };
|
|
251
|
+
if (visibility) body.visibility = visibility;
|
|
252
|
+
if (webhookUrl) body.webhookUrl = webhookUrl;
|
|
253
|
+
return await this.makeRequest('POST', `/api/assets/${fileId}/links`, body, { cache: false });
|
|
254
|
+
} catch (error) {
|
|
255
|
+
throw this.handleError(error);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Unlink asset from an entity
|
|
261
|
+
*/
|
|
262
|
+
async assetUnlink(fileId: string, app: string, entityType: string, entityId: string): Promise<any> {
|
|
263
|
+
try {
|
|
264
|
+
return await this.makeRequest('DELETE', `/api/assets/${fileId}/links`, {
|
|
265
|
+
app,
|
|
266
|
+
entityType,
|
|
267
|
+
entityId
|
|
268
|
+
}, { cache: false });
|
|
269
|
+
} catch (error) {
|
|
270
|
+
throw this.handleError(error);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Get asset metadata
|
|
276
|
+
*/
|
|
277
|
+
async assetGet(fileId: string): Promise<any> {
|
|
278
|
+
try {
|
|
279
|
+
return await this.makeRequest('GET', `/api/assets/${fileId}`, undefined, {
|
|
280
|
+
cache: true,
|
|
281
|
+
cacheTTL: 5 * 60 * 1000,
|
|
282
|
+
});
|
|
283
|
+
} catch (error) {
|
|
284
|
+
throw this.handleError(error);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Get asset URL (CDN or signed URL)
|
|
290
|
+
*/
|
|
291
|
+
async assetGetUrl(fileId: string, variant?: string, expiresIn?: number): Promise<AssetUrlResponse> {
|
|
292
|
+
try {
|
|
293
|
+
const params: any = {};
|
|
294
|
+
if (variant) params.variant = variant;
|
|
295
|
+
if (expiresIn) params.expiresIn = expiresIn;
|
|
296
|
+
|
|
297
|
+
return await this.makeRequest<AssetUrlResponse>('GET', `/api/assets/${fileId}/url`, params, {
|
|
298
|
+
cache: true,
|
|
299
|
+
cacheTTL: 10 * 60 * 1000,
|
|
300
|
+
});
|
|
301
|
+
} catch (error) {
|
|
302
|
+
throw this.handleError(error);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Restore asset from trash
|
|
308
|
+
*/
|
|
309
|
+
async assetRestore(fileId: string): Promise<any> {
|
|
310
|
+
try {
|
|
311
|
+
return await this.makeRequest('POST', `/api/assets/${fileId}/restore`, undefined, { cache: false });
|
|
312
|
+
} catch (error) {
|
|
313
|
+
throw this.handleError(error);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Delete asset with optional force
|
|
319
|
+
*/
|
|
320
|
+
async assetDelete(fileId: string, force: boolean = false): Promise<any> {
|
|
321
|
+
try {
|
|
322
|
+
const params: any = force ? { force: 'true' } : undefined;
|
|
323
|
+
return await this.makeRequest('DELETE', `/api/assets/${fileId}`, params, { cache: false });
|
|
324
|
+
} catch (error) {
|
|
325
|
+
throw this.handleError(error);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Get list of available variants for an asset
|
|
331
|
+
*/
|
|
332
|
+
async assetGetVariants(fileId: string): Promise<AssetVariant[]> {
|
|
333
|
+
try {
|
|
334
|
+
const assetData = await this.assetGet(fileId);
|
|
335
|
+
return assetData.file?.variants || [];
|
|
336
|
+
} catch (error) {
|
|
337
|
+
throw this.handleError(error);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Update asset visibility
|
|
343
|
+
*/
|
|
344
|
+
async assetUpdateVisibility(fileId: string, visibility: 'private' | 'public' | 'unlisted'): Promise<any> {
|
|
345
|
+
try {
|
|
346
|
+
return await this.makeRequest('PATCH', `/api/assets/${fileId}/visibility`, {
|
|
347
|
+
visibility
|
|
348
|
+
}, { cache: false });
|
|
349
|
+
} catch (error) {
|
|
350
|
+
throw this.handleError(error);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
async uploadAvatar(file: File, userId: string, app: string = 'profiles'): Promise<any> {
|
|
355
|
+
try {
|
|
356
|
+
const asset = await this.assetUpload(file, 'public');
|
|
357
|
+
await this.assetLink(asset.file.id, app, 'avatar', userId, 'public');
|
|
358
|
+
return asset;
|
|
359
|
+
} catch (error) {
|
|
360
|
+
throw this.handleError(error);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
async uploadProfileBanner(file: File, userId: string, app: string = 'profiles'): Promise<any> {
|
|
365
|
+
try {
|
|
366
|
+
const asset = await this.assetUpload(file, 'public');
|
|
367
|
+
await this.assetLink(asset.file.id, app, 'profile-banner', userId, 'public');
|
|
368
|
+
return asset;
|
|
369
|
+
} catch (error) {
|
|
370
|
+
throw this.handleError(error);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
public getAssetUrlCacheTTL(expiresIn?: number) {
|
|
375
|
+
const desiredTtlMs = (expiresIn ?? 3600) * 1000;
|
|
376
|
+
return Math.min(desiredTtlMs, 10 * 60 * 1000);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
public async fetchAssetDownloadUrl(
|
|
380
|
+
fileId: string,
|
|
381
|
+
variant?: string,
|
|
382
|
+
cacheTTL?: number,
|
|
383
|
+
expiresIn?: number
|
|
384
|
+
): Promise<string | null> {
|
|
385
|
+
const params: any = {};
|
|
386
|
+
if (variant) params.variant = variant;
|
|
387
|
+
if (expiresIn) params.expiresIn = expiresIn;
|
|
388
|
+
|
|
389
|
+
const urlRes = await this.makeRequest<{ url: string }>(
|
|
390
|
+
'GET',
|
|
391
|
+
`/api/assets/${encodeURIComponent(fileId)}/url`,
|
|
392
|
+
Object.keys(params).length ? params : undefined,
|
|
393
|
+
{
|
|
394
|
+
cache: true,
|
|
395
|
+
cacheTTL: cacheTTL ?? 10 * 60 * 1000,
|
|
396
|
+
}
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
return urlRes?.url || null;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
public async fetchAssetContent(url: string, type: 'text'): Promise<string>;
|
|
403
|
+
public async fetchAssetContent(url: string, type: 'blob'): Promise<Blob>;
|
|
404
|
+
public async fetchAssetContent(url: string, type: 'text' | 'blob') {
|
|
405
|
+
const response = await fetch(url, { credentials: 'include' });
|
|
406
|
+
if (!response?.ok) {
|
|
407
|
+
throw new Error(`Failed to fetch asset content (status ${response?.status})`);
|
|
408
|
+
}
|
|
409
|
+
return type === 'text' ? response.text() : response.blob();
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
}
|