Spaces:
Running
Running
incognitolm commited on
Commit ·
658aa72
1
Parent(s): bab7bd9
server/src/services/realtime.ts
CHANGED
|
@@ -701,7 +701,7 @@ export function initRealtime(httpServer: HttpServer): Server {
|
|
| 701 |
});
|
| 702 |
|
| 703 |
// ═══════════════════════════════════════════════
|
| 704 |
-
// PROJECT SYNC (
|
| 705 |
// ═══════════════════════════════════════════════
|
| 706 |
socket.on('project_sync', async (data: { projectId: string }, callback?: (response: any) => void) => {
|
| 707 |
try {
|
|
@@ -715,15 +715,14 @@ export function initRealtime(httpServer: HttpServer): Server {
|
|
| 715 |
return;
|
| 716 |
}
|
| 717 |
|
| 718 |
-
const {
|
| 719 |
-
const result = await
|
| 720 |
`projects/${user.userId}/${data.projectId}.enc`,
|
| 721 |
-
Buffer.from(project.encrypted_data)
|
| 722 |
-
`Project: ${project.name}`
|
| 723 |
);
|
| 724 |
|
| 725 |
if (result.success) {
|
| 726 |
-
if (callback) callback({ message: 'Project synced to
|
| 727 |
} else {
|
| 728 |
if (callback) callback({ error: 'Sync failed', details: result.message });
|
| 729 |
}
|
|
|
|
| 701 |
});
|
| 702 |
|
| 703 |
// ═══════════════════════════════════════════════
|
| 704 |
+
// PROJECT SYNC (sync to /data storage)
|
| 705 |
// ═══════════════════════════════════════════════
|
| 706 |
socket.on('project_sync', async (data: { projectId: string }, callback?: (response: any) => void) => {
|
| 707 |
try {
|
|
|
|
| 715 |
return;
|
| 716 |
}
|
| 717 |
|
| 718 |
+
const { uploadToStorage } = await import('./storage');
|
| 719 |
+
const result = await uploadToStorage(
|
| 720 |
`projects/${user.userId}/${data.projectId}.enc`,
|
| 721 |
+
Buffer.from(project.encrypted_data)
|
|
|
|
| 722 |
);
|
| 723 |
|
| 724 |
if (result.success) {
|
| 725 |
+
if (callback) callback({ message: 'Project synced to storage' });
|
| 726 |
} else {
|
| 727 |
if (callback) callback({ error: 'Sync failed', details: result.message });
|
| 728 |
}
|
server/src/services/storage.ts
CHANGED
|
@@ -1,91 +1,49 @@
|
|
| 1 |
-
import
|
|
|
|
| 2 |
|
| 3 |
-
|
| 4 |
-
success: boolean;
|
| 5 |
-
message?: string;
|
| 6 |
-
}
|
| 7 |
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
description?: string
|
| 12 |
-
): Promise<HFStorageResult> {
|
| 13 |
-
if (!config.hf.token || !config.hf.repoId) {
|
| 14 |
-
console.warn('HF storage not configured. Skipping upload.');
|
| 15 |
-
return { success: false, message: 'HF storage not configured' };
|
| 16 |
}
|
|
|
|
| 17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
try {
|
| 19 |
-
const
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
headers: {
|
| 23 |
-
Authorization: `Bearer ${config.hf.token}`,
|
| 24 |
-
'Content-Type': 'application/octet-stream',
|
| 25 |
-
...(description ? { 'X-Description': description } : {}),
|
| 26 |
-
},
|
| 27 |
-
body: data,
|
| 28 |
-
});
|
| 29 |
-
|
| 30 |
-
if (!response.ok) {
|
| 31 |
-
throw new Error(`HF storage upload failed: ${response.statusText}`);
|
| 32 |
-
}
|
| 33 |
-
|
| 34 |
return { success: true };
|
| 35 |
} catch (error: any) {
|
| 36 |
-
console.error('
|
| 37 |
return { success: false, message: error.message };
|
| 38 |
}
|
| 39 |
}
|
| 40 |
|
| 41 |
-
export async function
|
| 42 |
-
if (!config.hf.token || !config.hf.repoId) {
|
| 43 |
-
console.warn('HF storage not configured. Skipping download.');
|
| 44 |
-
return null;
|
| 45 |
-
}
|
| 46 |
-
|
| 47 |
try {
|
| 48 |
-
const
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
headers: {
|
| 52 |
-
Authorization: `Bearer ${config.hf.token}`,
|
| 53 |
-
},
|
| 54 |
-
});
|
| 55 |
-
|
| 56 |
-
if (!response.ok) {
|
| 57 |
-
if (response.status === 404) return null;
|
| 58 |
-
throw new Error(`HF storage download failed: ${response.statusText}`);
|
| 59 |
-
}
|
| 60 |
-
|
| 61 |
-
return Buffer.from(await response.arrayBuffer());
|
| 62 |
} catch (error: any) {
|
| 63 |
-
console.error('
|
| 64 |
return null;
|
| 65 |
}
|
| 66 |
}
|
| 67 |
|
| 68 |
-
export async function
|
| 69 |
-
if (!config.hf.token || !config.hf.repoId) {
|
| 70 |
-
return { success: false, message: 'HF storage not configured' };
|
| 71 |
-
}
|
| 72 |
-
|
| 73 |
try {
|
| 74 |
-
const
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
headers: {
|
| 78 |
-
Authorization: `Bearer ${config.hf.token}`,
|
| 79 |
-
},
|
| 80 |
-
});
|
| 81 |
-
|
| 82 |
-
if (!response.ok) {
|
| 83 |
-
throw new Error(`HF storage delete failed: ${response.statusText}`);
|
| 84 |
}
|
| 85 |
-
|
| 86 |
return { success: true };
|
| 87 |
} catch (error: any) {
|
| 88 |
-
console.error('
|
| 89 |
return { success: false, message: error.message };
|
| 90 |
}
|
| 91 |
}
|
|
|
|
| 1 |
+
import fs from 'fs';
|
| 2 |
+
import path from 'path';
|
| 3 |
|
| 4 |
+
const STORAGE_ROOT = process.env.STORAGE_PATH || '/data';
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
+
function ensureDir(dir: string) {
|
| 7 |
+
if (!fs.existsSync(dir)) {
|
| 8 |
+
fs.mkdirSync(dir, { recursive: true });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
}
|
| 10 |
+
}
|
| 11 |
|
| 12 |
+
export async function uploadToStorage(
|
| 13 |
+
filePath: string,
|
| 14 |
+
data: Buffer,
|
| 15 |
+
): Promise<{ success: boolean; message?: string }> {
|
| 16 |
try {
|
| 17 |
+
const fullPath = path.join(STORAGE_ROOT, filePath);
|
| 18 |
+
ensureDir(path.dirname(fullPath));
|
| 19 |
+
fs.writeFileSync(fullPath, data);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
return { success: true };
|
| 21 |
} catch (error: any) {
|
| 22 |
+
console.error('Storage write error:', error.message);
|
| 23 |
return { success: false, message: error.message };
|
| 24 |
}
|
| 25 |
}
|
| 26 |
|
| 27 |
+
export async function downloadFromStorage(filePath: string): Promise<Buffer | null> {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
try {
|
| 29 |
+
const fullPath = path.join(STORAGE_ROOT, filePath);
|
| 30 |
+
if (!fs.existsSync(fullPath)) return null;
|
| 31 |
+
return fs.readFileSync(fullPath);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
} catch (error: any) {
|
| 33 |
+
console.error('Storage read error:', error.message);
|
| 34 |
return null;
|
| 35 |
}
|
| 36 |
}
|
| 37 |
|
| 38 |
+
export async function deleteFromStorage(filePath: string): Promise<{ success: boolean; message?: string }> {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
try {
|
| 40 |
+
const fullPath = path.join(STORAGE_ROOT, filePath);
|
| 41 |
+
if (fs.existsSync(fullPath)) {
|
| 42 |
+
fs.unlinkSync(fullPath);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
}
|
|
|
|
| 44 |
return { success: true };
|
| 45 |
} catch (error: any) {
|
| 46 |
+
console.error('Storage delete error:', error.message);
|
| 47 |
return { success: false, message: error.message };
|
| 48 |
}
|
| 49 |
}
|