studio3d / src /utils /hfStorage.ts
Studio3D Deploy
๐Ÿš€ Initial Studio3D deployment โ€” React Three Fiber 3D Animation Studio
43024e4
/**
* Hugging Face XetHub Storage Helpers
*
* These utilities upload files to your HF Space's persistent storage
* (assets/ for GLB models, outputs/ for rendered videos).
*
* Requires the HF_TOKEN environment variable to be set as a Space Secret.
*
* Usage in your component:
* import { uploadAsset, uploadOutput } from '../utils/hfStorage';
* await uploadAsset(file, 'my-space/studio3d');
*/
const HF_API = 'https://huggingface.co/api';
/**
* Upload a GLB model to the Space's assets/ folder via HF API
*/
export async function uploadAsset(
file: File,
repoId: string,
hfToken: string
): Promise<string> {
const filename = `assets/${Date.now()}_${file.name}`;
return uploadToHF(file, repoId, filename, hfToken);
}
/**
* Upload a rendered video/image to the Space's outputs/ folder
*/
export async function uploadOutput(
blob: Blob,
filename: string,
repoId: string,
hfToken: string
): Promise<string> {
const file = new File([blob], filename, { type: blob.type });
const path = `outputs/${Date.now()}_${filename}`;
return uploadToHF(file, repoId, path, hfToken);
}
async function uploadToHF(
file: File,
repoId: string,
path: string,
hfToken: string
): Promise<string> {
const arrayBuffer = await file.arrayBuffer();
const response = await fetch(
`${HF_API}/spaces/${repoId}/upload/${encodeURIComponent(path)}`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${hfToken}`,
'Content-Type': file.type || 'application/octet-stream',
},
body: arrayBuffer,
}
);
if (!response.ok) {
throw new Error(`HF upload failed: ${response.statusText}`);
}
const data = await response.json();
// Return the public URL to the uploaded file
return `https://huggingface.co/spaces/${repoId}/resolve/main/${path}`;
}
/**
* List files in assets/ folder of the Space
*/
export async function listAssets(repoId: string, hfToken: string): Promise<string[]> {
const response = await fetch(
`${HF_API}/spaces/${repoId}/tree/main/assets`,
{
headers: { Authorization: `Bearer ${hfToken}` },
}
);
if (!response.ok) return [];
const data = await response.json();
return data.map((f: any) => f.path);
}
/**
* List files in outputs/ folder of the Space
*/
export async function listOutputs(repoId: string, hfToken: string): Promise<string[]> {
const response = await fetch(
`${HF_API}/spaces/${repoId}/tree/main/outputs`,
{
headers: { Authorization: `Bearer ${hfToken}` },
}
);
if (!response.ok) return [];
const data = await response.json();
return data.map((f: any) => f.path);
}