@clipwhisperer/common
Version:
ClipWhisperer Common - Shared library providing core utilities, database schemas, authentication, bucket management, and common functionality across all ClipWhisperer microservices
183 lines (158 loc) • 5.41 kB
text/typescript
import { Client } from "minio";
import { createVaultClient } from "./vault.js";
import z from "zod";
export type BucketManagerParams = {
vault: {
path: string;
schema: z.ZodObject<any>;
};
};
export default class BucketManager {
private minioClient: Client | null = null;
public readonly initializationPromise: Promise<void>;
private isInitialized: boolean = false;
/**
* Initializes the bucket manager
* @param params - The parameters for the bucket manager
*/
constructor(params: BucketManagerParams) {
this.initializationPromise = this.initialize(params);
}
/**
* Initializes the bucket manager's minio client
* @param params - The parameters for the bucket manager
*/
private async initialize(params: BucketManagerParams) {
try {
const vault = createVaultClient();
const apiKeys = await vault.readSecret(
params.vault.path,
params.vault.schema
);
const minioConfig = {
endPoint: process.env.MINIO_ENDPOINT || "localhost",
port: parseInt(process.env.MINIO_PORT || "9000"),
useSSL: process.env.MINIO_USE_SSL === "true",
accessKey: apiKeys.MINIO_ACCESS_KEY,
secretKey: apiKeys.MINIO_SECRET_KEY,
};
this.minioClient = new Client(minioConfig);
this.isInitialized = true;
console.log("✅ Bucket manager initialized successfully");
} catch (error) {
console.error("Error initializing bucket manager:", error);
this.isInitialized = false;
throw error;
}
}
/**
* Ensures the bucket manager is initialized before proceeding
*/
private async ensureInitialized(): Promise<void> {
if (!this.isInitialized) {
await this.initializationPromise;
}
if (!this.minioClient) {
throw new Error("Minio client not initialized");
}
}
/**
* Checks if a bucket exists and creates it if it doesn't
* @param bucketName - The name of the bucket to check
* @returns {Promise<boolean>} True if the bucket exists, false otherwise
*/
async checkBucketExists(bucketName: string): Promise<boolean> {
await this.ensureInitialized();
const exists = await this.minioClient!.bucketExists(bucketName);
if (!exists) {
await this.minioClient!.makeBucket(bucketName);
console.log(`✅ Created bucket: ${bucketName}`);
}
return exists;
}
/**
* Uploads a file to a bucket
* @param bucketName - The name of the bucket to upload to
* @param filePath - The path to the file to upload
* @param objectName - The name of the object to upload
* @param metadata - Optional metadata to add to the file
*/
async uploadFile(
bucketName: string,
filePath: string,
objectName: string,
metadata?: Record<string, string>
) {
await this.ensureInitialized();
await this.checkBucketExists(bucketName);
await this.minioClient!.fPutObject(
bucketName,
objectName,
filePath,
metadata
);
console.log(`✅ Successfully uploaded: ${bucketName}/${objectName}`);
}
/**
* Gets a video file from a bucket
* @param bucketName - The name of the bucket
* @param videoUuid - The UUID of the video
* @param uuid - The user UUID
* @returns {Promise<string>} The URL or path to the video file
*/
async getVideo(
bucketName: string,
videoUuid: string,
uuid: string
): Promise<string> {
await this.ensureInitialized();
await this.checkBucketExists(bucketName);
const objectName = `${uuid}/${videoUuid}/video.mp4`;
// Check if the video exists
try {
await this.minioClient!.statObject(bucketName, objectName);
console.log(`✅ Video found: ${bucketName}/${objectName}`);
// Return the presigned URL for the video (valid for 1 hour)
const presignedUrl = await this.minioClient!.presignedGetObject(
bucketName,
objectName,
3600
);
return presignedUrl;
} catch (error) {
console.error(`❌ Video not found: ${bucketName}/${objectName}`);
throw new Error(`Video not found: ${objectName}`);
}
}
/**
* Gets a thumbnail image from a bucket
* @param bucketName - The name of the bucket
* @param videoUuid - The UUID of the video
* @param uuid - The user UUID
* @returns {Promise<string>} The URL or path to the thumbnail image
*/
async getThumbnail(
bucketName: string,
videoUuid: string,
uuid: string
): Promise<string> {
await this.ensureInitialized();
await this.checkBucketExists(bucketName);
const objectName = `${uuid}/${videoUuid}/thumbnail.jpg`;
// Check if the thumbnail exists
try {
await this.minioClient!.statObject(bucketName, objectName);
console.log(`✅ Thumbnail found: ${bucketName}/${objectName}`);
// Return the presigned URL for the thumbnail (valid for 1 hour)
const presignedUrl = await this.minioClient!.presignedGetObject(
bucketName,
objectName,
3600
);
return presignedUrl;
} catch (error) {
console.error(`❌ Thumbnail not found: ${bucketName}/${objectName}`);
throw new Error(`Thumbnail not found: ${objectName}`);
}
}
}