Files
ai-wpa/lib/file-vault.ts
2025-08-30 18:18:57 +05:30

153 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* File upload service using external API
* Replaces MINIO with custom file upload API
*/
import { env } from './env'
// File upload result from the API
export interface FileUploadResponse {
success: boolean
url: string
filename: string
}
// File upload result for internal use
export interface UploadResult {
url: string
filename: string
originalName: string
size: number
type: string
uploadedAt: string
}
/**
* Upload file to external API
*/
export async function uploadFile(
buffer: Buffer,
filename: string,
contentType: string,
userId?: string
): Promise<UploadResult> {
console.log('📤 Starting file upload:', { filename, contentType, bufferSize: buffer.length })
try {
// Create FormData for multipart upload
const formData = new FormData()
const blob = new Blob([buffer], { type: contentType })
formData.append('file', blob, filename)
// Prepare headers
const headers: Record<string, string> = {
'x-user-data': userId || 'default-user',
Authorization: `Bearer ${env.FILE_UPLOAD_TOKEN || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlRlc3QgVXNlciIsImlhdCI6MTUxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'}`,
}
console.log('📤 Uploading to external API:', {
url: process.env.UPLOAD_API_URL,
filename,
size: buffer.length,
userId: userId || 'default-user',
})
// Make the upload request
const response = await fetch(process.env.UPLOAD_API_URL, {
method: 'POST',
headers,
body: formData,
})
if (!response.ok) {
const errorText = await response.text()
throw new Error(`Upload failed: ${response.status} ${response.statusText} - ${errorText}`)
}
const result: FileUploadResponse = await response.json()
if (!result.success) {
throw new Error('Upload API returned success: false')
}
console.log('✅ File uploaded successfully:', result)
return {
url: result.url,
filename: result.filename,
originalName: filename,
size: buffer.length,
type: contentType,
uploadedAt: new Date().toISOString(),
}
} catch (error) {
console.error('❌ Error uploading file:', error)
throw error
}
}
/**
* Generate unique filename with timestamp and random string
*/
export function generateUniqueFilename(originalName: string): string {
const timestamp = Date.now()
const randomString = Math.random().toString(36).substring(2)
const extension = originalName.split('.').pop()
return `${timestamp}-${randomString}.${extension}`
}
/**
* Validate file type
*/
export function validateFileType(mimetype: string, allowedTypes: string[]): boolean {
return allowedTypes.includes(mimetype)
}
/**
* Validate file size (in bytes)
*/
export function validateFileSize(size: number, maxSize: number): boolean {
return size <= maxSize
}
/**
* Get file URL (files are already publicly accessible)
*/
export async function getFileUrl(filePath: string): Promise<string> {
// Files from the upload API are already publicly accessible
// If filePath is already a full URL, return it as is
if (filePath.startsWith('http')) {
return filePath
}
// Otherwise, construct the URL using the delivery base URL
return `${process.env.DELIVERY_BASE_URL}/${filePath}`
}
/**
* Delete file (not supported by the current API)
*/
export async function deleteFile(filePath: string): Promise<void> {
console.warn('⚠️ File deletion not supported by current upload API:', filePath)
// The external API doesn't provide a delete endpoint
// This is a no-op for now
}
/**
* Move file to permanent storage (not needed with new API)
*/
export async function moveToPermStorage(tempPath: string, permanentPath: string): Promise<void> {
console.log(' Move to permanent storage not needed with new API')
// The new API directly uploads to permanent storage
// This is a no-op
}
/**
* Initialize bucket (not needed with new API)
*/
export async function initializeBucket(): Promise<void> {
console.log(' Bucket initialization not needed with new API')
// The new API handles storage internally
// This is a no-op
}