initial commit
This commit is contained in:
186
lib/minio.ts
Normal file
186
lib/minio.ts
Normal file
@@ -0,0 +1,186 @@
|
||||
import { Client } from 'minio'
|
||||
import { env } from './env'
|
||||
|
||||
// Get MinIO credentials with dev-portfolio naming first, fallback to legacy names
|
||||
const minioAccessKey = env.MINIO_KEY || env.MINIO_ACCESS_KEY
|
||||
const minioSecretKey = env.MINIO_SECRET || env.MINIO_SECRET_KEY
|
||||
const minioBucket = env.MINIO_IMAGE_BUCKET || env.MINIO_BUCKET
|
||||
|
||||
// Only initialize MinIO client if ALL required configuration is available
|
||||
export const minioClient = (env.MINIO_ENDPOINT && minioAccessKey && minioSecretKey)
|
||||
? new Client({
|
||||
endPoint: env.MINIO_ENDPOINT,
|
||||
port: env.MINIO_PORT || 9000,
|
||||
useSSL: env.NODE_ENV === 'production',
|
||||
accessKey: minioAccessKey,
|
||||
secretKey: minioSecretKey,
|
||||
})
|
||||
: null
|
||||
|
||||
// Log MinIO initialization status
|
||||
if (!minioClient) {
|
||||
console.warn('⚠️ MinIO client not initialized. Missing configuration:', {
|
||||
hasEndpoint: !!env.MINIO_ENDPOINT,
|
||||
hasKey: !!minioAccessKey,
|
||||
hasSecret: !!minioSecretKey,
|
||||
checkedVars: ['MINIO_KEY/MINIO_ACCESS_KEY', 'MINIO_SECRET/MINIO_SECRET_KEY']
|
||||
})
|
||||
} else {
|
||||
console.log('✅ MinIO client initialized successfully with endpoint:', env.MINIO_ENDPOINT)
|
||||
}
|
||||
|
||||
export const BUCKET_NAME = minioBucket || 'nextjs-boilerplate'
|
||||
|
||||
// Initialize bucket if it doesn't exist
|
||||
export async function initializeBucket() {
|
||||
if (!minioClient) {
|
||||
console.error('❌ MinIO client not configured for bucket initialization')
|
||||
throw new Error(
|
||||
'MinIO client not configured. Please set MINIO_ENDPOINT, MINIO_ACCESS_KEY, and MINIO_SECRET_KEY environment variables.'
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('🔍 Checking if bucket exists:', BUCKET_NAME)
|
||||
const bucketExists = await minioClient.bucketExists(BUCKET_NAME)
|
||||
|
||||
if (!bucketExists) {
|
||||
console.log('🚀 Creating bucket:', BUCKET_NAME)
|
||||
await minioClient.makeBucket(BUCKET_NAME, 'us-east-1')
|
||||
console.log('✅ Bucket created successfully:', BUCKET_NAME)
|
||||
} else {
|
||||
console.log('✅ Bucket already exists:', BUCKET_NAME)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Error initializing bucket:', {
|
||||
error: error.message,
|
||||
code: error.code,
|
||||
statusCode: error.statusCode,
|
||||
bucketName: BUCKET_NAME,
|
||||
endpoint: env.MINIO_ENDPOINT,
|
||||
port: env.MINIO_PORT
|
||||
})
|
||||
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}`
|
||||
}
|
||||
|
||||
// Upload file to MinIO
|
||||
export async function uploadFile(
|
||||
buffer: Buffer,
|
||||
filename: string,
|
||||
contentType: string
|
||||
): Promise<string> {
|
||||
console.log('📤 Starting file upload:', { filename, contentType, bufferSize: buffer.length })
|
||||
|
||||
if (!minioClient) {
|
||||
console.error('❌ MinIO client not configured')
|
||||
throw new Error(
|
||||
'MinIO client not configured. Please set MINIO_ENDPOINT, MINIO_ACCESS_KEY, and MINIO_SECRET_KEY environment variables.'
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('🔧 Initializing bucket:', BUCKET_NAME)
|
||||
await initializeBucket()
|
||||
|
||||
const uniqueFilename = generateUniqueFilename(filename)
|
||||
const tempPath = `temp/${uniqueFilename}`
|
||||
|
||||
console.log('📤 Uploading to MinIO:', {
|
||||
bucket: BUCKET_NAME,
|
||||
path: tempPath,
|
||||
size: buffer.length,
|
||||
endpoint: env.MINIO_ENDPOINT,
|
||||
port: env.MINIO_PORT,
|
||||
useSSL: env.NODE_ENV === 'production'
|
||||
})
|
||||
|
||||
await minioClient.putObject(BUCKET_NAME, tempPath, buffer, buffer.length, {
|
||||
'Content-Type': contentType,
|
||||
})
|
||||
|
||||
console.log('✅ File uploaded successfully:', tempPath)
|
||||
return tempPath
|
||||
} catch (error) {
|
||||
console.error('❌ Error uploading file:', {
|
||||
error: error.message,
|
||||
code: error.code,
|
||||
statusCode: error.statusCode,
|
||||
resource: error.resource,
|
||||
region: error.region,
|
||||
bucketName: error.bucketName,
|
||||
objectName: error.objectName,
|
||||
})
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// Move file from temp to permanent storage
|
||||
export async function moveToPermStorage(tempPath: string, permanentPath: string): Promise<void> {
|
||||
if (!minioClient) {
|
||||
throw new Error(
|
||||
'MinIO client not configured. Please set MINIO_ENDPOINT, MINIO_ACCESS_KEY, and MINIO_SECRET_KEY environment variables.'
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
// Copy from temp to permanent location
|
||||
await minioClient.copyObject(BUCKET_NAME, permanentPath, `${BUCKET_NAME}/${tempPath}`)
|
||||
|
||||
// Remove from temp location
|
||||
await minioClient.removeObject(BUCKET_NAME, tempPath)
|
||||
} catch (error) {
|
||||
console.error('Error moving file to permanent storage:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// Delete file from storage
|
||||
export async function deleteFile(filePath: string): Promise<void> {
|
||||
if (!minioClient) {
|
||||
throw new Error(
|
||||
'MinIO client not configured. Please set MINIO_ENDPOINT, MINIO_ACCESS_KEY, and MINIO_SECRET_KEY environment variables.'
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
await minioClient.removeObject(BUCKET_NAME, filePath)
|
||||
} catch (error) {
|
||||
console.error('Error deleting file:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// Get file URL (for serving files)
|
||||
export async function getFileUrl(filePath: string): Promise<string> {
|
||||
if (!minioClient) {
|
||||
throw new Error(
|
||||
'MinIO client not configured. Please set MINIO_ENDPOINT, MINIO_ACCESS_KEY, and MINIO_SECRET_KEY environment variables.'
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
return await minioClient.presignedGetObject(BUCKET_NAME, filePath, 7 * 24 * 60 * 60) // 7 days
|
||||
} catch (error) {
|
||||
console.error('Error getting file URL:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user