@oxyhq/services
Version:
Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀
260 lines (243 loc) • 7.21 kB
JavaScript
;
import { useCallback } from 'react';
import { useAssetStore } from '../stores/assetStore';
// Create a singleton instance for the hook
let oxyInstance = null;
export const setOxyAssetInstance = instance => {
oxyInstance = instance;
};
/**
* Hook for managing assets with Zustand store integration
*/
export const useAssets = () => {
const {
assets,
uploadProgress,
loading,
errors,
setAsset,
setAssets,
removeAsset,
setUploadProgress,
removeUploadProgress,
addLink,
removeLink,
setUploading,
setLinking,
setDeleting,
setUploadError,
setLinkError,
setDeleteError,
clearErrors,
getAssetsByApp,
getAssetsByEntity,
getAssetUsageCount,
isAssetLinked,
reset
} = useAssetStore();
// Upload asset with progress tracking
const upload = useCallback(async (file, metadata) => {
if (!oxyInstance) {
throw new Error('OxyServices instance not configured. Call setOxyAssetInstance first.');
}
try {
clearErrors();
setUploading(true);
// Calculate SHA256 for progress tracking
const sha256 = await oxyInstance.calculateSHA256(file);
// Initialize progress tracking
const initialProgress = {
fileId: '',
// Will be set after init
uploaded: 0,
total: file.size,
percentage: 0,
status: 'uploading'
};
// Upload with progress callback (visibility undefined, metadata, then onProgress)
const result = await oxyInstance.assetUpload(file, undefined, metadata, percentage => {
if (initialProgress.fileId) {
setUploadProgress(initialProgress.fileId, {
...initialProgress,
uploaded: Math.round(percentage / 100 * file.size),
percentage,
status: percentage < 100 ? 'uploading' : 'processing'
});
}
});
// Update progress with final status
if (result.file && initialProgress.fileId) {
setUploadProgress(initialProgress.fileId, {
...initialProgress,
fileId: result.file.id,
uploaded: file.size,
percentage: 100,
status: 'complete'
});
// Remove progress after a short delay
setTimeout(() => {
removeUploadProgress(result.file.id);
}, 2000);
}
// Add asset to store
if (result.file) {
setAsset(result.file);
return result.file;
}
return null;
} catch (error) {
setUploadError(error.message || 'Upload failed');
throw error;
} finally {
setUploading(false);
}
}, [clearErrors, setUploading, setUploadProgress, removeUploadProgress, setAsset, setUploadError]);
// Link asset to entity
const link = useCallback(async (assetId, app, entityType, entityId) => {
if (!oxyInstance) {
throw new Error('OxyServices instance not configured. Call setOxyAssetInstance first.');
}
try {
clearErrors();
setLinking(true);
// Auto-detect visibility for avatars and profile banners
const visibility = entityType === 'avatar' || entityType === 'profile-banner' ? 'public' : undefined;
const result = await oxyInstance.assetLink(assetId, app, entityType, entityId, visibility);
if (result.file) {
setAsset(result.file);
} else {
// If API doesn't return full file, update store optimistically
addLink(assetId, {
app,
entityType,
entityId,
createdBy: '',
// Will be filled by server
createdAt: new Date().toISOString()
});
}
} catch (error) {
setLinkError(error.message || 'Link failed');
throw error;
} finally {
setLinking(false);
}
}, [clearErrors, setLinking, setAsset, addLink, setLinkError]);
// Unlink asset from entity
const unlink = useCallback(async (assetId, app, entityType, entityId) => {
if (!oxyInstance) {
throw new Error('OxyServices instance not configured. Call setOxyAssetInstance first.');
}
try {
clearErrors();
setLinking(true);
const result = await oxyInstance.assetUnlink(assetId, app, entityType, entityId);
if (result.file) {
setAsset(result.file);
} else {
// Update store optimistically
removeLink(assetId, app, entityType, entityId);
}
} catch (error) {
setLinkError(error.message || 'Unlink failed');
throw error;
} finally {
setLinking(false);
}
}, [clearErrors, setLinking, setAsset, removeLink, setLinkError]);
// Get asset URL
const getUrl = useCallback(async (assetId, variant, expiresIn) => {
if (!oxyInstance) {
throw new Error('OxyServices instance not configured. Call setOxyAssetInstance first.');
}
try {
const result = await oxyInstance.assetGetUrl(assetId, variant, expiresIn);
return result.url;
} catch (error) {
throw error;
}
}, []);
// Get asset metadata
const getAsset = useCallback(async assetId => {
if (!oxyInstance) {
throw new Error('OxyServices instance not configured. Call setOxyAssetInstance first.');
}
try {
const result = await oxyInstance.assetGet(assetId);
if (result.file) {
setAsset(result.file);
return result.file;
}
throw new Error('Asset not found');
} catch (error) {
throw error;
}
}, [setAsset]);
// Delete asset
const deleteAsset = useCallback(async (assetId, force = false) => {
if (!oxyInstance) {
throw new Error('OxyServices instance not configured. Call setOxyAssetInstance first.');
}
try {
clearErrors();
setDeleting(true);
await oxyInstance.assetDelete(assetId, force);
removeAsset(assetId);
} catch (error) {
setDeleteError(error.message || 'Delete failed');
throw error;
} finally {
setDeleting(false);
}
}, [clearErrors, setDeleting, removeAsset, setDeleteError]);
// Restore asset from trash
const restore = useCallback(async assetId => {
if (!oxyInstance) {
throw new Error('OxyServices instance not configured. Call setOxyAssetInstance first.');
}
try {
const result = await oxyInstance.assetRestore(assetId);
if (result.file) {
setAsset(result.file);
}
} catch (error) {
throw error;
}
}, [setAsset]);
// Get variants
const getVariants = useCallback(async assetId => {
if (!oxyInstance) {
throw new Error('OxyServices instance not configured. Call setOxyAssetInstance first.');
}
try {
return await oxyInstance.assetGetVariants(assetId);
} catch (error) {
throw error;
}
}, []);
return {
// State
assets: Object.values(assets),
uploadProgress,
loading,
errors,
// Actions
upload,
link,
unlink,
getUrl,
getAsset,
deleteAsset,
restore,
getVariants,
// Utility methods
getAssetsByApp,
getAssetsByEntity,
getAssetUsageCount,
isAssetLinked,
// Store management
clearErrors,
reset
};
};
//# sourceMappingURL=useAssets.js.map