import * as plugins from './smartbucket.plugins.js'; import { SmartBucket } from './smartbucket.classes.smartbucket.js'; import { Directory } from './smartbucket.classes.directory.js'; export class Bucket { public static async getBucketByName(smartbucketRef: SmartBucket, bucketNameArg: string) { const buckets = await smartbucketRef.minioClient.listBuckets(); const foundBucket = buckets.find((bucket) => { return bucket.name === bucketNameArg; }); if (foundBucket) { console.log(`bucket with name ${bucketNameArg} exists.`); console.log(`Taking this as base for new Bucket instance`); return new this(smartbucketRef, bucketNameArg); } else { return null; } } public static async createBucketByName(smartbucketRef: SmartBucket, bucketName: string) { await smartbucketRef.minioClient.makeBucket(bucketName, 'ams3').catch((e) => console.log(e)); return new Bucket(smartbucketRef, bucketName); } public static async removeBucketByName(smartbucketRef: SmartBucket, bucketName: string) { await smartbucketRef.minioClient.removeBucket(bucketName).catch((e) => console.log(e)); } public smartbucketRef: SmartBucket; public name: string; constructor(smartbucketRef: SmartBucket, bucketName: string) { this.smartbucketRef = smartbucketRef; this.name = bucketName; } /** * gets the base directory of the bucket */ public async getBaseDirectory() { return new Directory(this, null, ''); } // =============== // Fast Operations // =============== /** * store file */ public async fastPut(optionsArg: { path: string; contents: string | Buffer; }): Promise { const streamIntake = new plugins.smartstream.StreamIntake(); const putPromise = this.smartbucketRef.minioClient .putObject(this.name, optionsArg.path, streamIntake) .catch((e) => console.log(e)); streamIntake.pushData(optionsArg.contents); streamIntake.signalEnd(); const response = await putPromise; } /** * get file */ public async fastGet(optionsArg: Parameters[0]): Promise { const done = plugins.smartpromise.defer(); let completeFile: Buffer; const replaySubject = await this.fastGetStream(optionsArg); const subscription = replaySubject.subscribe({ next: (chunk) => { if (completeFile) { completeFile = Buffer.concat([completeFile, chunk]); } else { completeFile = chunk; } }, complete: () => { done.resolve(); subscription.unsubscribe(); }, error: (err) => { console.log(err); }, }); await done.promise; return completeFile; } public async fastGetStream(optionsArg: { path: string; }): Promise> { const fileStream = await this.smartbucketRef.minioClient .getObject(this.name, optionsArg.path) .catch((e) => console.log(e)); const replaySubject = new plugins.smartrx.rxjs.ReplaySubject(); const duplexStream = new plugins.smartstream.SmartDuplex({ writeFunction: async (chunk) => { replaySubject.next(chunk); return chunk; }, finalFunction: async (cb) => { replaySubject.complete(); return Buffer.from(''); } }); if (!fileStream) { return null; } const smartstream = new plugins.smartstream.StreamWrapper([ fileStream, duplexStream, ]); smartstream.run(); return replaySubject; } /** * store file as stream */ public async fastPutStream(optionsArg: { path: string; dataStream: plugins.stream.Readable; nativeMetadata?: { [key: string]: string }; }): Promise { await this.smartbucketRef.minioClient.putObject( this.name, optionsArg.path, optionsArg.dataStream, null, ...(optionsArg.nativeMetadata ? (() => { const returnObject: any = {}; return returnObject; })() : {}) ); } public async copyObject(optionsArg: { /** * the */ objectKey: string; /** * in case you want to copy to another bucket specify it here */ targetBucket?: Bucket; targetBucketKey?: string; /** * metadata will be merged with existing metadata */ nativeMetadata?: { [key: string]: string }; deleteExistingNativeMetadata?: boolean; }): Promise { try { const targetBucketName = optionsArg.targetBucket ? optionsArg.targetBucket.name : this.name; // Retrieve current object information to use in copy conditions const currentObjInfo = await this.smartbucketRef.minioClient.statObject( targetBucketName, optionsArg.objectKey ); // Setting up copy conditions const copyConditions = new plugins.minio.CopyConditions(); // Prepare new metadata const newNativeMetadata = { ...(optionsArg.deleteExistingNativeMetadata ? {} : currentObjInfo.metaData), ...optionsArg.nativeMetadata, }; // Define the copy operation as a Promise // TODO: check on issue here: https://github.com/minio/minio-js/issues/1286 await this.smartbucketRef.minioClient.copyObject( this.name, optionsArg.objectKey, `/${targetBucketName}/${optionsArg.objectKey}`, copyConditions ); } catch (err) { console.error('Error updating metadata:', err); throw err; // rethrow to allow caller to handle } } /** * removeObject */ public async fastRemove(optionsArg: { path: string; }) { await this.smartbucketRef.minioClient.removeObject(this.name, optionsArg.path); } public async doesObjectExist(optionsArg: { path: string; }): Promise { try { await this.smartbucketRef.minioClient.statObject(this.name, optionsArg.path); console.log(`Object '${optionsArg.path}' exists in bucket '${this.name}'.`); return true; } catch (error) { if (error.code === 'NotFound') { console.log(`Object '${optionsArg.path}' does not exist in bucket '${this.name}'.`); return false; } else { console.error('Error checking object existence:', error); throw error; // Rethrow if it's not a NotFound error to handle unexpected issues } } } }