chatapi / src /handlers /fileHandler.ts
wilooper's picture
initial commit
87cb242
Raw History Blame Contribute Delete
2.67 kB
import WebSocket from 'ws';
import { ClientMessage, safeSend } from '../utils/protocol';
import {
generateUploadUrl,
validateFileRequest,
validateFileCount,
FileUploadRequest,
} from '../services/supabaseService';
import { logger } from '../utils/logger';
/**
* Handles type: 'get-upload-url'
*
* Client sends:
* {
* files: Array<{ fileName: string, mimeType: string, sizeBytes: number }>
* }
*
* Server responds with:
* {
* urls: Array<{ signedUrl, objectPath, publicUrl, fileName }>
* }
*
* The client then PUTs each file directly to Supabase using the signedUrl.
* HF server never sees any file bytes β€” memory usage stays near 0.
*
* After upload, the client sends a type: 'message' with type: 'media' and
* the publicUrl as the content field.
*/
export async function handleFileRequest(
ws: WebSocket,
uid: string,
msg: ClientMessage
): Promise<void> {
const files = msg.payload.files as FileUploadRequest[] | undefined;
// ── Validate count ────────────────────────────────────────────────────────
if (!Array.isArray(files)) {
safeSend(ws, 'error', { message: 'files must be an array' }, msg.requestId);
return;
}
const countError = validateFileCount(files.length);
if (countError) {
safeSend(ws, 'error', { message: countError }, msg.requestId);
return;
}
// ── Validate each file ────────────────────────────────────────────────────
for (const f of files) {
const fileError = validateFileRequest(f);
if (fileError) {
safeSend(ws, 'error', { message: fileError }, msg.requestId);
return;
}
}
// ── Generate signed URLs ──────────────────────────────────────────────────
try {
const results = await Promise.all(
files.map(async (f) => {
const result = await generateUploadUrl(uid, f);
return {
fileName: f.fileName,
signedUrl: result.signedUrl,
objectPath: result.objectPath,
publicUrl: result.publicUrl,
};
})
);
safeSend(ws, 'upload-url', { urls: results }, msg.requestId);
logger.info('Signed URLs generated', { uid, count: results.length });
} catch (err) {
logger.error('generateUploadUrl failed', { uid, error: String(err) });
safeSend(ws, 'error', { message: 'Failed to generate upload URL' }, msg.requestId);
}
}