Files
pn-new-crm/src/lib/minio/index.ts

64 lines
1.7 KiB
TypeScript
Raw Normal View History

import { Client } from 'minio';
import { env } from '@/lib/env';
import { logger } from '@/lib/logger';
export const minioClient = new Client({
endPoint: env.MINIO_ENDPOINT,
port: env.MINIO_PORT,
useSSL: env.MINIO_USE_SSL,
accessKey: env.MINIO_ACCESS_KEY,
secretKey: env.MINIO_SECRET_KEY,
});
const BUCKET = env.MINIO_BUCKET;
/**
* Ensures the configured bucket exists, creating it if not.
* Should be called once at application startup.
*/
export async function ensureBucket(): Promise<void> {
try {
const exists = await minioClient.bucketExists(BUCKET);
if (!exists) {
await minioClient.makeBucket(BUCKET);
logger.info({ bucket: BUCKET }, 'MinIO bucket created');
} else {
logger.debug({ bucket: BUCKET }, 'MinIO bucket exists');
}
} catch (err) {
logger.error({ err, bucket: BUCKET }, 'Failed to ensure MinIO bucket');
throw err;
}
}
/**
* Generates a pre-signed GET URL for an object.
*
* Default expiry is 15 minutes (900 seconds) per SECURITY-GUIDELINES.md §7.1.
*/
export async function getPresignedUrl(
objectKey: string,
expirySeconds = 900,
): Promise<string> {
return minioClient.presignedGetObject(BUCKET, objectKey, expirySeconds);
}
/**
* Constructs a storage path from typed components.
*
* Format: `{portSlug}/{entity}/{entityId}/{fileId}.{extension}`
*
* No user-supplied input should ever be used as path components only UUIDs
* and controlled slugs (SECURITY-GUIDELINES.md §3.4, §7.1).
*/
export function buildStoragePath(
portSlug: string,
entity: string,
entityId: string,
fileId: string,
extension: string,
): string {
return `${portSlug}/${entity}/${entityId}/${fileId}.${extension}`;
}