Files
nullcart/backend/src/config/uploadPaths.ts
T
nobswebdev abe6208e4e Add blog thumbnail and banner upload endpoints with storage keys.
Store image filenames in DB, resolve paths for cleanup on replace/delete, and reuse product-thumb multer limits.
2026-09-16 11:40:05 +02:00

71 lines
2.4 KiB
TypeScript

import { join, resolve, sep } from 'node:path';
const uploadsRoot = (): string => join(process.cwd(), 'uploads');
const validatePathTraversal = (baseDir: string, absolutePath: string): void => {
const resolvedBaseDir = resolve(baseDir);
if (!absolutePath.startsWith(`${resolvedBaseDir}${sep}`)) {
throw new Error('Invalid storage key');
}
};
const resolvePathWithinDir = (baseDir: string, storageKey: string): string => {
const resolvedBaseDir = resolve(baseDir);
const absolutePath = resolve(resolvedBaseDir, storageKey);
validatePathTraversal(resolvedBaseDir, absolutePath);
return absolutePath;
};
export const getPublicUploadsDir = (): string => join(uploadsRoot(), 'public');
export const publicUploadsUrlPrefix = '/uploads/public/';
export const getPrivateUploadsDir = (): string => join(uploadsRoot(), 'private');
export const getVariantImagesDir = (): string => join(getPublicUploadsDir(), 'variants', 'images');
export const variantImagesUrlPrefix = '/uploads/public/variants/images/';
export const getVariantImagePublicUrl = (filename: string): string => `${variantImagesUrlPrefix}${filename}`;
export const getBlogImagesDir = (): string => join(getPublicUploadsDir(), 'blog', 'images');
export const blogImagesUrlPrefix = '/uploads/public/blog/images/';
export const getBlogImagePublicUrl = (filename: string): string => `${blogImagesUrlPrefix}${filename}`;
export const resolveBlogImagePath = (storageKey: string): string => {
const baseDir = getBlogImagesDir();
const absolutePath = resolvePathWithinDir(baseDir, storageKey);
return absolutePath;
};
export const getShopBrandingDir = (): string => join(getPublicUploadsDir(), 'shop');
export const shopBrandingUrlPrefix = '/uploads/public/shop/';
export const getShopBrandingPublicUrl = (filename: string): string => `${shopBrandingUrlPrefix}${filename}`;
export const resolveShopBrandingPath = (storageKey: string): string => {
const baseDir = getShopBrandingDir();
const absolutePath = resolvePathWithinDir(baseDir, storageKey);
return absolutePath;
};
export const getDigitalStockAttachmentsDir = (): string => join(getPrivateUploadsDir(), 'digital-stock', 'attachments');
export const resolveDigitalStockAttachmentPath = (storageKey: string): string => {
const baseDir = getDigitalStockAttachmentsDir();
const absolutePath = resolvePathWithinDir(baseDir, storageKey);
return absolutePath;
};