129 lines
3.6 KiB
TypeScript
129 lines
3.6 KiB
TypeScript
import { uploadToS3 } from '@/lib/s3'
|
|
|
|
export const PUBLIC_DISPLAY_PREFIX = 'public-display'
|
|
|
|
function normalizeRelativePath(relativePath: string): string {
|
|
return String(relativePath || '')
|
|
.trim()
|
|
.replace(/\\/g, '/')
|
|
.replace(/^\/+/, '')
|
|
.replace(/\/{2,}/g, '/')
|
|
}
|
|
|
|
function normalizeS3PublicDomain(): string | null {
|
|
const rawDomain = String(process.env.S3_PUBLIC_DOMAIN || '').trim()
|
|
if (!rawDomain) {
|
|
return null
|
|
}
|
|
|
|
const normalized = rawDomain.match(/^https?:\/\//i) ? rawDomain : `https://${rawDomain}`
|
|
return normalized.replace(/\/+$/, '')
|
|
}
|
|
|
|
export function buildPublicDisplayObjectPath(relativePath: string): string {
|
|
const normalized = normalizeRelativePath(relativePath)
|
|
if (!normalized) {
|
|
return PUBLIC_DISPLAY_PREFIX
|
|
}
|
|
|
|
return `${PUBLIC_DISPLAY_PREFIX}/${normalized}`
|
|
}
|
|
|
|
function buildStorageObjectPath(objectPath: string): string {
|
|
const normalizedPrefix = normalizeRelativePath(process.env.S3_FILE_PATH || '')
|
|
const normalizedObjectPath = normalizeRelativePath(objectPath)
|
|
|
|
if (!normalizedPrefix) {
|
|
return normalizedObjectPath
|
|
}
|
|
|
|
return normalizeRelativePath(`${normalizedPrefix}/${normalizedObjectPath}`)
|
|
}
|
|
|
|
export function buildPublicDisplayUrl(relativePath: string): string | null {
|
|
const publicDomain = normalizeS3PublicDomain()
|
|
const objectPath = buildPublicDisplayObjectPath(relativePath)
|
|
|
|
if (!publicDomain || !objectPath) {
|
|
return null
|
|
}
|
|
|
|
return `${publicDomain}/${buildStorageObjectPath(objectPath)}`
|
|
}
|
|
|
|
export async function uploadPublicDisplayToS3(
|
|
file: Buffer,
|
|
relativePath: string,
|
|
contentType: string,
|
|
): Promise<string> {
|
|
return uploadToS3(file, buildPublicDisplayObjectPath(relativePath), contentType)
|
|
}
|
|
|
|
export function buildMaterialPublicDisplayPath(fileName: string): string {
|
|
return normalizeRelativePath(`materials/${fileName}`)
|
|
}
|
|
|
|
export function buildTaskDetailPublicDisplayPath(
|
|
materialId: string,
|
|
group: 'main' | 'sku' | 'detail',
|
|
fileName: string,
|
|
): string {
|
|
return normalizeRelativePath(`task-detail/${materialId}/${group}/${fileName}`)
|
|
}
|
|
|
|
export function buildCertificateReportPublicDisplayPath(
|
|
materialId: string,
|
|
group: 'pdf' | 'image' | 'preview',
|
|
fileName: string,
|
|
): string {
|
|
return normalizeRelativePath(`certificate-report/${materialId}/${group}/${fileName}`)
|
|
}
|
|
|
|
export function buildWhiteBackgroundPublicDisplayPath(
|
|
materialId: string,
|
|
skuId: string,
|
|
fileName: string,
|
|
): string {
|
|
return normalizeRelativePath(`white-background/${materialId}/${skuId}/${fileName}`)
|
|
}
|
|
|
|
export function buildWhiteBackgroundPublicDisplayPathFromAssetPath(
|
|
fileUrl?: string | null,
|
|
): string | null {
|
|
const normalizedFileUrl = String(fileUrl || '').trim().replace(/\\/g, '/')
|
|
if (!normalizedFileUrl || /^https?:\/\//i.test(normalizedFileUrl)) {
|
|
return null
|
|
}
|
|
|
|
const normalizedRelativePath = normalizedFileUrl.replace(/^\.?\//, '')
|
|
const segments = normalizedRelativePath.split('/').filter(Boolean)
|
|
const whiteBackgroundIndex = segments.indexOf('white-background')
|
|
|
|
if (
|
|
whiteBackgroundIndex < 0 ||
|
|
whiteBackgroundIndex < 2 ||
|
|
!segments[whiteBackgroundIndex - 1] ||
|
|
!segments[whiteBackgroundIndex + 1]
|
|
) {
|
|
return null
|
|
}
|
|
|
|
const materialId = segments[whiteBackgroundIndex - 1]
|
|
const skuId = segments[whiteBackgroundIndex + 1]
|
|
const fileSegments = segments.slice(whiteBackgroundIndex + 2)
|
|
|
|
if (fileSegments.length === 0) {
|
|
return null
|
|
}
|
|
|
|
if (fileSegments[0] === 'preview') {
|
|
fileSegments.shift()
|
|
}
|
|
|
|
if (fileSegments.length === 0) {
|
|
return null
|
|
}
|
|
|
|
return buildWhiteBackgroundPublicDisplayPath(materialId, skuId, fileSegments.join('/'))
|
|
}
|