Apply full refactor updates plus pipeline/email UX confirmations
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m33s
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m33s
This commit is contained in:
@@ -1,131 +1,131 @@
|
||||
import type { StorageProvider, StorageProviderType } from './types'
|
||||
import { S3StorageProvider } from './s3-provider'
|
||||
import { LocalStorageProvider } from './local-provider'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
export type { StorageProvider, StorageProviderType } from './types'
|
||||
export { S3StorageProvider } from './s3-provider'
|
||||
export { LocalStorageProvider } from './local-provider'
|
||||
|
||||
// Cached provider instance
|
||||
let cachedProvider: StorageProvider | null = null
|
||||
let cachedProviderType: StorageProviderType | null = null
|
||||
|
||||
/**
|
||||
* Get the configured storage provider type from system settings
|
||||
*/
|
||||
async function getProviderTypeFromSettings(): Promise<StorageProviderType> {
|
||||
try {
|
||||
const setting = await prisma.systemSettings.findUnique({
|
||||
where: { key: 'storage_provider' },
|
||||
})
|
||||
const value = setting?.value as StorageProviderType | undefined
|
||||
return value === 'local' ? 'local' : 's3' // Default to S3
|
||||
} catch {
|
||||
// If settings table doesn't exist or error, default to S3
|
||||
return 's3'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current storage provider type from settings
|
||||
*/
|
||||
export async function getCurrentProviderType(): Promise<StorageProviderType> {
|
||||
return getProviderTypeFromSettings()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a storage provider instance based on system settings
|
||||
* Caches the provider for performance
|
||||
*/
|
||||
export async function getStorageProvider(): Promise<StorageProvider> {
|
||||
const providerType = await getProviderTypeFromSettings()
|
||||
|
||||
// Return cached provider if type hasn't changed
|
||||
if (cachedProvider && cachedProviderType === providerType) {
|
||||
return cachedProvider
|
||||
}
|
||||
|
||||
// Create new provider
|
||||
if (providerType === 'local') {
|
||||
cachedProvider = new LocalStorageProvider()
|
||||
} else {
|
||||
cachedProvider = new S3StorageProvider()
|
||||
}
|
||||
cachedProviderType = providerType
|
||||
|
||||
return cachedProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a storage provider and its type together
|
||||
*/
|
||||
export async function getStorageProviderWithType(): Promise<{
|
||||
provider: StorageProvider
|
||||
providerType: StorageProviderType
|
||||
}> {
|
||||
const providerType = await getProviderTypeFromSettings()
|
||||
const provider = await getStorageProvider()
|
||||
return { provider, providerType }
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a specific storage provider (bypasses settings)
|
||||
*/
|
||||
export function createStorageProvider(type: StorageProviderType): StorageProvider {
|
||||
if (type === 'local') {
|
||||
return new LocalStorageProvider()
|
||||
}
|
||||
return new S3StorageProvider()
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cached provider (call when settings change)
|
||||
*/
|
||||
export function clearStorageProviderCache(): void {
|
||||
cachedProvider = null
|
||||
cachedProviderType = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique storage key for avatars
|
||||
*/
|
||||
export function generateAvatarKey(userId: string, fileName: string): string {
|
||||
const timestamp = Date.now()
|
||||
const ext = fileName.split('.').pop() || 'jpg'
|
||||
return `avatars/${userId}/${timestamp}.${ext}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique storage key for project logos
|
||||
*/
|
||||
export function generateLogoKey(projectId: string, fileName: string): string {
|
||||
const timestamp = Date.now()
|
||||
const ext = fileName.split('.').pop() || 'png'
|
||||
return `logos/${projectId}/${timestamp}.${ext}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content type from file extension
|
||||
*/
|
||||
export function getContentType(fileName: string): string {
|
||||
const ext = fileName.toLowerCase().split('.').pop()
|
||||
const types: Record<string, string> = {
|
||||
jpg: 'image/jpeg',
|
||||
jpeg: 'image/jpeg',
|
||||
png: 'image/png',
|
||||
gif: 'image/gif',
|
||||
webp: 'image/webp',
|
||||
svg: 'image/svg+xml',
|
||||
pdf: 'application/pdf',
|
||||
}
|
||||
return types[ext || ''] || 'application/octet-stream'
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate image file type
|
||||
*/
|
||||
export function isValidImageType(contentType: string): boolean {
|
||||
const validTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
|
||||
return validTypes.includes(contentType)
|
||||
}
|
||||
import type { StorageProvider, StorageProviderType } from './types'
|
||||
import { S3StorageProvider } from './s3-provider'
|
||||
import { LocalStorageProvider } from './local-provider'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
export type { StorageProvider, StorageProviderType } from './types'
|
||||
export { S3StorageProvider } from './s3-provider'
|
||||
export { LocalStorageProvider } from './local-provider'
|
||||
|
||||
// Cached provider instance
|
||||
let cachedProvider: StorageProvider | null = null
|
||||
let cachedProviderType: StorageProviderType | null = null
|
||||
|
||||
/**
|
||||
* Get the configured storage provider type from system settings
|
||||
*/
|
||||
async function getProviderTypeFromSettings(): Promise<StorageProviderType> {
|
||||
try {
|
||||
const setting = await prisma.systemSettings.findUnique({
|
||||
where: { key: 'storage_provider' },
|
||||
})
|
||||
const value = setting?.value as StorageProviderType | undefined
|
||||
return value === 'local' ? 'local' : 's3' // Default to S3
|
||||
} catch {
|
||||
// If settings table doesn't exist or error, default to S3
|
||||
return 's3'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current storage provider type from settings
|
||||
*/
|
||||
export async function getCurrentProviderType(): Promise<StorageProviderType> {
|
||||
return getProviderTypeFromSettings()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a storage provider instance based on system settings
|
||||
* Caches the provider for performance
|
||||
*/
|
||||
export async function getStorageProvider(): Promise<StorageProvider> {
|
||||
const providerType = await getProviderTypeFromSettings()
|
||||
|
||||
// Return cached provider if type hasn't changed
|
||||
if (cachedProvider && cachedProviderType === providerType) {
|
||||
return cachedProvider
|
||||
}
|
||||
|
||||
// Create new provider
|
||||
if (providerType === 'local') {
|
||||
cachedProvider = new LocalStorageProvider()
|
||||
} else {
|
||||
cachedProvider = new S3StorageProvider()
|
||||
}
|
||||
cachedProviderType = providerType
|
||||
|
||||
return cachedProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a storage provider and its type together
|
||||
*/
|
||||
export async function getStorageProviderWithType(): Promise<{
|
||||
provider: StorageProvider
|
||||
providerType: StorageProviderType
|
||||
}> {
|
||||
const providerType = await getProviderTypeFromSettings()
|
||||
const provider = await getStorageProvider()
|
||||
return { provider, providerType }
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a specific storage provider (bypasses settings)
|
||||
*/
|
||||
export function createStorageProvider(type: StorageProviderType): StorageProvider {
|
||||
if (type === 'local') {
|
||||
return new LocalStorageProvider()
|
||||
}
|
||||
return new S3StorageProvider()
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cached provider (call when settings change)
|
||||
*/
|
||||
export function clearStorageProviderCache(): void {
|
||||
cachedProvider = null
|
||||
cachedProviderType = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique storage key for avatars
|
||||
*/
|
||||
export function generateAvatarKey(userId: string, fileName: string): string {
|
||||
const timestamp = Date.now()
|
||||
const ext = fileName.split('.').pop() || 'jpg'
|
||||
return `avatars/${userId}/${timestamp}.${ext}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique storage key for project logos
|
||||
*/
|
||||
export function generateLogoKey(projectId: string, fileName: string): string {
|
||||
const timestamp = Date.now()
|
||||
const ext = fileName.split('.').pop() || 'png'
|
||||
return `logos/${projectId}/${timestamp}.${ext}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content type from file extension
|
||||
*/
|
||||
export function getContentType(fileName: string): string {
|
||||
const ext = fileName.toLowerCase().split('.').pop()
|
||||
const types: Record<string, string> = {
|
||||
jpg: 'image/jpeg',
|
||||
jpeg: 'image/jpeg',
|
||||
png: 'image/png',
|
||||
gif: 'image/gif',
|
||||
webp: 'image/webp',
|
||||
svg: 'image/svg+xml',
|
||||
pdf: 'application/pdf',
|
||||
}
|
||||
return types[ext || ''] || 'application/octet-stream'
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate image file type
|
||||
*/
|
||||
export function isValidImageType(contentType: string): boolean {
|
||||
const validTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
|
||||
return validTypes.includes(contentType)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user