2024-06-17 14:01:35 +00:00
|
|
|
// classes.bucket.ts
|
|
|
|
|
2024-05-20 23:22:21 +00:00
|
|
|
import * as plugins from './plugins.js';
|
2024-05-27 10:56:25 +00:00
|
|
|
import * as helpers from './helpers.js';
|
|
|
|
import * as interfaces from './interfaces.js';
|
2024-05-20 23:22:21 +00:00
|
|
|
import { SmartBucket } from './classes.smartbucket.js';
|
|
|
|
import { Directory } from './classes.directory.js';
|
2024-05-27 10:56:25 +00:00
|
|
|
import { File } from './classes.file.js';
|
2024-06-10 14:47:20 +00:00
|
|
|
import { Trash } from './classes.trash.js';
|
2019-10-14 18:55:07 +00:00
|
|
|
|
2024-06-10 14:47:20 +00:00
|
|
|
/**
|
2024-06-17 14:01:35 +00:00
|
|
|
* The bucket class exposes the basic functionality of a bucket.
|
2024-06-10 14:47:20 +00:00
|
|
|
* The functions of the bucket alone are enough to
|
2024-06-17 14:01:35 +00:00
|
|
|
* operate in S3 basic fashion on blobs of data.
|
2024-06-10 14:47:20 +00:00
|
|
|
*/
|
2019-10-15 12:16:28 +00:00
|
|
|
export class Bucket {
|
2019-10-15 17:23:06 +00:00
|
|
|
public static async getBucketByName(smartbucketRef: SmartBucket, bucketNameArg: string) {
|
2024-06-17 14:01:35 +00:00
|
|
|
const command = new plugins.s3.ListBucketsCommand({});
|
|
|
|
const buckets = await smartbucketRef.s3Client.send(command);
|
|
|
|
const foundBucket = buckets.Buckets.find((bucket) => bucket.Name === bucketNameArg);
|
2019-10-15 12:16:28 +00:00
|
|
|
|
|
|
|
if (foundBucket) {
|
2019-10-16 17:15:48 +00:00
|
|
|
console.log(`bucket with name ${bucketNameArg} exists.`);
|
2019-10-15 12:16:28 +00:00
|
|
|
console.log(`Taking this as base for new Bucket instance`);
|
|
|
|
return new this(smartbucketRef, bucketNameArg);
|
2019-10-15 17:23:06 +00:00
|
|
|
} else {
|
2024-07-28 10:46:39 +00:00
|
|
|
console.log(`did not find bucket by name: ${bucketNameArg}`);
|
2019-10-15 17:23:06 +00:00
|
|
|
return null;
|
2019-10-15 12:16:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-15 17:23:06 +00:00
|
|
|
public static async createBucketByName(smartbucketRef: SmartBucket, bucketName: string) {
|
2024-06-17 14:01:35 +00:00
|
|
|
const command = new plugins.s3.CreateBucketCommand({ Bucket: bucketName });
|
|
|
|
await smartbucketRef.s3Client.send(command).catch((e) => console.log(e));
|
2019-10-15 17:23:06 +00:00
|
|
|
return new Bucket(smartbucketRef, bucketName);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static async removeBucketByName(smartbucketRef: SmartBucket, bucketName: string) {
|
2024-06-17 14:01:35 +00:00
|
|
|
const command = new plugins.s3.DeleteBucketCommand({ Bucket: bucketName });
|
|
|
|
await smartbucketRef.s3Client.send(command).catch((e) => console.log(e));
|
2019-10-15 17:23:06 +00:00
|
|
|
}
|
|
|
|
|
2019-10-15 12:16:28 +00:00
|
|
|
public smartbucketRef: SmartBucket;
|
|
|
|
public name: string;
|
2019-10-15 17:23:06 +00:00
|
|
|
|
2019-10-15 12:16:28 +00:00
|
|
|
constructor(smartbucketRef: SmartBucket, bucketName: string) {
|
|
|
|
this.smartbucketRef = smartbucketRef;
|
|
|
|
this.name = bucketName;
|
|
|
|
}
|
2019-10-15 17:23:06 +00:00
|
|
|
|
2019-10-16 17:11:28 +00:00
|
|
|
/**
|
|
|
|
* gets the base directory of the bucket
|
|
|
|
*/
|
2024-05-27 10:56:25 +00:00
|
|
|
public async getBaseDirectory(): Promise<Directory> {
|
2019-10-16 17:11:28 +00:00
|
|
|
return new Directory(this, null, '');
|
|
|
|
}
|
|
|
|
|
2024-06-10 14:47:20 +00:00
|
|
|
/**
|
|
|
|
* gets the trash directory
|
|
|
|
*/
|
|
|
|
public async getTrash(): Promise<Trash> {
|
|
|
|
const trash = new Trash(this);
|
|
|
|
return trash;
|
|
|
|
}
|
|
|
|
|
|
|
|
public async getDirectoryFromPath(
|
|
|
|
pathDescriptorArg: interfaces.IPathDecriptor
|
|
|
|
): Promise<Directory> {
|
2024-05-27 10:56:25 +00:00
|
|
|
if (!pathDescriptorArg.path && !pathDescriptorArg.directory) {
|
|
|
|
return this.getBaseDirectory();
|
|
|
|
}
|
2024-06-17 14:01:35 +00:00
|
|
|
const checkPath = await helpers.reducePathDescriptorToPath(pathDescriptorArg);
|
2024-05-27 10:56:25 +00:00
|
|
|
const baseDirectory = await this.getBaseDirectory();
|
|
|
|
return await baseDirectory.getSubDirectoryByName(checkPath);
|
|
|
|
}
|
|
|
|
|
2019-10-16 16:12:18 +00:00
|
|
|
// ===============
|
|
|
|
// Fast Operations
|
|
|
|
// ===============
|
|
|
|
|
2019-10-15 17:23:06 +00:00
|
|
|
/**
|
|
|
|
* store file
|
|
|
|
*/
|
2024-06-17 14:01:35 +00:00
|
|
|
public async fastPut(
|
|
|
|
optionsArg: interfaces.IPathDecriptor & {
|
|
|
|
contents: string | Buffer;
|
|
|
|
overwrite?: boolean;
|
|
|
|
}
|
|
|
|
): Promise<File> {
|
2024-05-20 23:22:21 +00:00
|
|
|
try {
|
2024-06-10 14:47:20 +00:00
|
|
|
const reducedPath = await helpers.reducePathDescriptorToPath(optionsArg);
|
2024-05-27 10:56:25 +00:00
|
|
|
const exists = await this.fastExists({ path: reducedPath });
|
2024-06-10 14:47:20 +00:00
|
|
|
|
2024-05-20 23:22:21 +00:00
|
|
|
if (exists && !optionsArg.overwrite) {
|
2024-05-27 10:56:25 +00:00
|
|
|
console.error(`Object already exists at path '${reducedPath}' in bucket '${this.name}'.`);
|
2024-05-20 23:22:21 +00:00
|
|
|
return;
|
|
|
|
} else if (exists && optionsArg.overwrite) {
|
2024-06-10 14:47:20 +00:00
|
|
|
console.log(
|
|
|
|
`Overwriting existing object at path '${reducedPath}' in bucket '${this.name}'.`
|
|
|
|
);
|
2024-05-20 23:22:21 +00:00
|
|
|
} else {
|
2024-05-27 10:56:25 +00:00
|
|
|
console.log(`Creating new object at path '${reducedPath}' in bucket '${this.name}'.`);
|
2024-05-20 23:22:21 +00:00
|
|
|
}
|
2024-06-10 14:47:20 +00:00
|
|
|
|
2024-06-17 14:01:35 +00:00
|
|
|
const command = new plugins.s3.PutObjectCommand({
|
|
|
|
Bucket: this.name,
|
|
|
|
Key: reducedPath,
|
|
|
|
Body: optionsArg.contents,
|
|
|
|
});
|
|
|
|
await this.smartbucketRef.s3Client.send(command);
|
2024-06-10 14:47:20 +00:00
|
|
|
|
2024-05-27 10:56:25 +00:00
|
|
|
console.log(`Object '${reducedPath}' has been successfully stored in bucket '${this.name}'.`);
|
|
|
|
const parsedPath = plugins.path.parse(reducedPath);
|
|
|
|
return new File({
|
|
|
|
directoryRefArg: await this.getDirectoryFromPath({
|
|
|
|
path: parsedPath.dir,
|
|
|
|
}),
|
|
|
|
fileName: parsedPath.base,
|
|
|
|
});
|
2024-05-20 23:22:21 +00:00
|
|
|
} catch (error) {
|
2024-06-10 14:47:20 +00:00
|
|
|
console.error(
|
|
|
|
`Error storing object at path '${optionsArg.path}' in bucket '${this.name}':`,
|
|
|
|
error
|
|
|
|
);
|
2024-05-20 23:22:21 +00:00
|
|
|
throw error;
|
|
|
|
}
|
2019-10-16 13:21:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* get file
|
|
|
|
*/
|
2024-06-10 14:47:20 +00:00
|
|
|
public async fastGet(optionsArg: { path: string }): Promise<Buffer> {
|
2019-10-16 13:21:02 +00:00
|
|
|
const done = plugins.smartpromise.defer();
|
2020-06-19 00:42:26 +00:00
|
|
|
let completeFile: Buffer;
|
2024-06-03 19:35:08 +00:00
|
|
|
const replaySubject = await this.fastGetReplaySubject(optionsArg);
|
2024-05-17 16:53:11 +00:00
|
|
|
const subscription = replaySubject.subscribe({
|
|
|
|
next: (chunk) => {
|
2020-06-19 00:42:26 +00:00
|
|
|
if (completeFile) {
|
|
|
|
completeFile = Buffer.concat([completeFile, chunk]);
|
2021-04-07 19:01:35 +00:00
|
|
|
} else {
|
|
|
|
completeFile = chunk;
|
2020-06-19 00:42:26 +00:00
|
|
|
}
|
2019-10-20 10:27:58 +00:00
|
|
|
},
|
2024-05-17 16:53:11 +00:00
|
|
|
complete: () => {
|
2019-10-20 10:27:58 +00:00
|
|
|
done.resolve();
|
2021-04-07 18:42:03 +00:00
|
|
|
subscription.unsubscribe();
|
2024-05-17 16:53:11 +00:00
|
|
|
},
|
|
|
|
error: (err) => {
|
|
|
|
console.log(err);
|
|
|
|
},
|
|
|
|
});
|
2019-10-20 10:27:58 +00:00
|
|
|
await done.promise;
|
|
|
|
return completeFile;
|
|
|
|
}
|
|
|
|
|
2024-06-03 19:35:08 +00:00
|
|
|
/**
|
|
|
|
* good when time to first byte is important
|
|
|
|
* and multiple subscribers are expected
|
|
|
|
* @param optionsArg
|
2024-06-10 14:47:20 +00:00
|
|
|
* @returns
|
2024-06-03 19:35:08 +00:00
|
|
|
*/
|
|
|
|
public async fastGetReplaySubject(optionsArg: {
|
2024-05-17 16:53:11 +00:00
|
|
|
path: string;
|
|
|
|
}): Promise<plugins.smartrx.rxjs.ReplaySubject<Buffer>> {
|
2024-06-17 14:01:35 +00:00
|
|
|
const command = new plugins.s3.GetObjectCommand({
|
|
|
|
Bucket: this.name,
|
|
|
|
Key: optionsArg.path,
|
2024-05-17 16:53:11 +00:00
|
|
|
});
|
2024-06-17 14:01:35 +00:00
|
|
|
const response = await this.smartbucketRef.s3Client.send(command);
|
|
|
|
const replaySubject = new plugins.smartrx.rxjs.ReplaySubject<Buffer>();
|
2019-10-16 13:21:02 +00:00
|
|
|
|
2024-06-17 14:01:35 +00:00
|
|
|
// Convert the stream to a format that supports piping
|
|
|
|
const stream = response.Body as any; // SdkStreamMixin includes readable stream
|
|
|
|
if (typeof stream.pipe === 'function') {
|
|
|
|
const duplexStream = new plugins.smartstream.SmartDuplex<Buffer, void>({
|
|
|
|
writeFunction: async (chunk) => {
|
|
|
|
replaySubject.next(chunk);
|
|
|
|
return;
|
|
|
|
},
|
|
|
|
finalFunction: async (cb) => {
|
|
|
|
replaySubject.complete();
|
|
|
|
return;
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
stream.pipe(duplexStream);
|
2019-10-16 13:21:02 +00:00
|
|
|
}
|
|
|
|
|
2019-10-20 10:27:58 +00:00
|
|
|
return replaySubject;
|
2019-10-16 13:21:02 +00:00
|
|
|
}
|
|
|
|
|
2024-06-10 14:47:20 +00:00
|
|
|
public fastGetStream(
|
|
|
|
optionsArg: {
|
|
|
|
path: string;
|
|
|
|
},
|
|
|
|
typeArg: 'webstream'
|
|
|
|
): Promise<ReadableStream>;
|
|
|
|
public async fastGetStream(
|
|
|
|
optionsArg: {
|
|
|
|
path: string;
|
|
|
|
},
|
|
|
|
typeArg: 'nodestream'
|
|
|
|
): Promise<plugins.stream.Readable>;
|
2024-06-03 19:35:08 +00:00
|
|
|
|
2024-06-10 14:47:20 +00:00
|
|
|
public async fastGetStream(
|
|
|
|
optionsArg: { path: string },
|
|
|
|
typeArg: 'webstream' | 'nodestream' = 'nodestream'
|
|
|
|
): Promise<ReadableStream | plugins.stream.Readable> {
|
2024-06-17 14:01:35 +00:00
|
|
|
const command = new plugins.s3.GetObjectCommand({
|
|
|
|
Bucket: this.name,
|
|
|
|
Key: optionsArg.path,
|
|
|
|
});
|
|
|
|
const response = await this.smartbucketRef.s3Client.send(command);
|
|
|
|
const stream = response.Body as any; // SdkStreamMixin includes readable stream
|
|
|
|
|
2024-06-03 19:35:08 +00:00
|
|
|
const duplexStream = new plugins.smartstream.SmartDuplex<Buffer, Buffer>({
|
|
|
|
writeFunction: async (chunk) => {
|
|
|
|
return chunk;
|
|
|
|
},
|
|
|
|
finalFunction: async (cb) => {
|
|
|
|
return null;
|
2024-06-10 14:47:20 +00:00
|
|
|
},
|
2024-06-03 19:35:08 +00:00
|
|
|
});
|
|
|
|
|
2024-06-17 14:01:35 +00:00
|
|
|
if (typeof stream.pipe === 'function') {
|
|
|
|
stream.pipe(duplexStream);
|
2024-06-03 19:35:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (typeArg === 'nodestream') {
|
|
|
|
return duplexStream;
|
2024-06-10 14:47:20 +00:00
|
|
|
}
|
2024-06-03 19:35:08 +00:00
|
|
|
if (typeArg === 'webstream') {
|
|
|
|
return (await duplexStream.getWebStreams()).readable;
|
|
|
|
}
|
2024-11-18 14:07:46 +00:00
|
|
|
throw new Error('unknown typeArg');
|
2024-06-03 19:35:08 +00:00
|
|
|
}
|
|
|
|
|
2024-05-05 17:52:50 +00:00
|
|
|
/**
|
|
|
|
* store file as stream
|
|
|
|
*/
|
|
|
|
public async fastPutStream(optionsArg: {
|
2024-05-17 16:53:11 +00:00
|
|
|
path: string;
|
2024-06-09 14:02:33 +00:00
|
|
|
readableStream: plugins.stream.Readable | ReadableStream;
|
2024-05-17 16:53:11 +00:00
|
|
|
nativeMetadata?: { [key: string]: string };
|
2024-05-20 23:22:21 +00:00
|
|
|
overwrite?: boolean;
|
2024-05-05 17:52:50 +00:00
|
|
|
}): Promise<void> {
|
2024-05-20 23:22:21 +00:00
|
|
|
try {
|
|
|
|
const exists = await this.fastExists({ path: optionsArg.path });
|
2024-06-10 14:47:20 +00:00
|
|
|
|
2024-05-20 23:22:21 +00:00
|
|
|
if (exists && !optionsArg.overwrite) {
|
2024-06-10 14:47:20 +00:00
|
|
|
console.error(
|
|
|
|
`Object already exists at path '${optionsArg.path}' in bucket '${this.name}'.`
|
|
|
|
);
|
2024-05-20 23:22:21 +00:00
|
|
|
return;
|
|
|
|
} else if (exists && optionsArg.overwrite) {
|
2024-06-10 14:47:20 +00:00
|
|
|
console.log(
|
|
|
|
`Overwriting existing object at path '${optionsArg.path}' in bucket '${this.name}'.`
|
|
|
|
);
|
2024-05-20 23:22:21 +00:00
|
|
|
} else {
|
|
|
|
console.log(`Creating new object at path '${optionsArg.path}' in bucket '${this.name}'.`);
|
|
|
|
}
|
2024-06-03 19:35:08 +00:00
|
|
|
|
2024-06-17 14:01:35 +00:00
|
|
|
const command = new plugins.s3.PutObjectCommand({
|
|
|
|
Bucket: this.name,
|
|
|
|
Key: optionsArg.path,
|
|
|
|
Body: optionsArg.readableStream,
|
|
|
|
Metadata: optionsArg.nativeMetadata,
|
|
|
|
});
|
|
|
|
await this.smartbucketRef.s3Client.send(command);
|
2024-06-10 14:47:20 +00:00
|
|
|
|
|
|
|
console.log(
|
|
|
|
`Object '${optionsArg.path}' has been successfully stored in bucket '${this.name}'.`
|
2024-05-20 23:22:21 +00:00
|
|
|
);
|
|
|
|
} catch (error) {
|
2024-06-10 14:47:20 +00:00
|
|
|
console.error(
|
|
|
|
`Error storing object at path '${optionsArg.path}' in bucket '${this.name}':`,
|
|
|
|
error
|
|
|
|
);
|
2024-05-20 23:22:21 +00:00
|
|
|
throw error;
|
|
|
|
}
|
2024-05-05 17:52:50 +00:00
|
|
|
}
|
|
|
|
|
2024-05-27 10:56:25 +00:00
|
|
|
public async fastCopy(optionsArg: {
|
|
|
|
sourcePath: string;
|
|
|
|
destinationPath?: string;
|
2024-05-17 16:53:11 +00:00
|
|
|
targetBucket?: Bucket;
|
|
|
|
nativeMetadata?: { [key: string]: string };
|
|
|
|
deleteExistingNativeMetadata?: boolean;
|
|
|
|
}): Promise<void> {
|
2024-05-05 17:52:50 +00:00
|
|
|
try {
|
2024-05-17 16:53:11 +00:00
|
|
|
const targetBucketName = optionsArg.targetBucket ? optionsArg.targetBucket.name : this.name;
|
|
|
|
|
2024-05-05 17:52:50 +00:00
|
|
|
// Retrieve current object information to use in copy conditions
|
2024-06-17 14:01:35 +00:00
|
|
|
const currentObjInfo = await this.smartbucketRef.s3Client.send(
|
|
|
|
new plugins.s3.HeadObjectCommand({
|
|
|
|
Bucket: this.name,
|
|
|
|
Key: optionsArg.sourcePath,
|
|
|
|
})
|
2024-05-17 16:53:11 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
// Prepare new metadata
|
|
|
|
const newNativeMetadata = {
|
2024-06-17 14:01:35 +00:00
|
|
|
...(optionsArg.deleteExistingNativeMetadata ? {} : currentObjInfo.Metadata),
|
2024-05-17 16:53:11 +00:00
|
|
|
...optionsArg.nativeMetadata,
|
2024-05-05 17:52:50 +00:00
|
|
|
};
|
2024-05-17 16:53:11 +00:00
|
|
|
|
2024-06-17 14:01:35 +00:00
|
|
|
// Define the copy operation
|
|
|
|
const copySource = `${this.name}/${optionsArg.sourcePath}`;
|
|
|
|
const command = new plugins.s3.CopyObjectCommand({
|
|
|
|
Bucket: targetBucketName,
|
|
|
|
CopySource: copySource,
|
|
|
|
Key: optionsArg.destinationPath || optionsArg.sourcePath,
|
|
|
|
Metadata: newNativeMetadata,
|
|
|
|
MetadataDirective: optionsArg.deleteExistingNativeMetadata ? 'REPLACE' : 'COPY',
|
|
|
|
});
|
|
|
|
await this.smartbucketRef.s3Client.send(command);
|
2024-05-05 17:52:50 +00:00
|
|
|
} catch (err) {
|
|
|
|
console.error('Error updating metadata:', err);
|
|
|
|
throw err; // rethrow to allow caller to handle
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-10 14:47:20 +00:00
|
|
|
/**
|
2024-05-27 10:56:25 +00:00
|
|
|
* Move object from one path to another within the same bucket or to another bucket
|
|
|
|
*/
|
2024-06-10 14:47:20 +00:00
|
|
|
public async fastMove(optionsArg: {
|
|
|
|
sourcePath: string;
|
|
|
|
destinationPath: string;
|
|
|
|
targetBucket?: Bucket;
|
|
|
|
overwrite?: boolean;
|
|
|
|
}): Promise<void> {
|
|
|
|
try {
|
|
|
|
const destinationBucket = optionsArg.targetBucket || this;
|
|
|
|
const exists = await destinationBucket.fastExists({ path: optionsArg.destinationPath });
|
|
|
|
|
|
|
|
if (exists && !optionsArg.overwrite) {
|
|
|
|
console.error(
|
|
|
|
`Object already exists at destination path '${optionsArg.destinationPath}' in bucket '${destinationBucket.name}'.`
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
} else if (exists && optionsArg.overwrite) {
|
|
|
|
console.log(
|
|
|
|
`Overwriting existing object at destination path '${optionsArg.destinationPath}' in bucket '${destinationBucket.name}'.`
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
console.log(
|
|
|
|
`Moving object to path '${optionsArg.destinationPath}' in bucket '${destinationBucket.name}'.`
|
|
|
|
);
|
2024-05-27 10:56:25 +00:00
|
|
|
}
|
2024-06-10 14:47:20 +00:00
|
|
|
|
|
|
|
await this.fastCopy(optionsArg);
|
|
|
|
await this.fastRemove({ path: optionsArg.sourcePath });
|
|
|
|
|
|
|
|
console.log(
|
|
|
|
`Object '${optionsArg.sourcePath}' has been successfully moved to '${optionsArg.destinationPath}' in bucket '${destinationBucket.name}'.`
|
|
|
|
);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(
|
|
|
|
`Error moving object from '${optionsArg.sourcePath}' to '${optionsArg.destinationPath}':`,
|
|
|
|
error
|
|
|
|
);
|
|
|
|
throw error;
|
2024-05-27 10:56:25 +00:00
|
|
|
}
|
2024-06-10 14:47:20 +00:00
|
|
|
}
|
2024-05-27 10:56:25 +00:00
|
|
|
|
2019-10-16 13:21:02 +00:00
|
|
|
/**
|
|
|
|
* removeObject
|
|
|
|
*/
|
2024-06-10 14:47:20 +00:00
|
|
|
public async fastRemove(optionsArg: { path: string }) {
|
2024-06-17 14:01:35 +00:00
|
|
|
const command = new plugins.s3.DeleteObjectCommand({
|
|
|
|
Bucket: this.name,
|
|
|
|
Key: optionsArg.path,
|
|
|
|
});
|
|
|
|
await this.smartbucketRef.s3Client.send(command);
|
2024-05-17 16:53:11 +00:00
|
|
|
}
|
|
|
|
|
2024-05-20 23:22:21 +00:00
|
|
|
/**
|
2024-06-17 14:01:35 +00:00
|
|
|
* check whether file exists
|
2024-05-20 23:22:21 +00:00
|
|
|
* @param optionsArg
|
2024-06-10 14:47:20 +00:00
|
|
|
* @returns
|
2024-05-20 23:22:21 +00:00
|
|
|
*/
|
2024-06-10 14:47:20 +00:00
|
|
|
public async fastExists(optionsArg: { path: string }): Promise<boolean> {
|
2024-05-17 16:53:11 +00:00
|
|
|
try {
|
2024-06-17 14:01:35 +00:00
|
|
|
const command = new plugins.s3.HeadObjectCommand({
|
|
|
|
Bucket: this.name,
|
|
|
|
Key: optionsArg.path,
|
|
|
|
});
|
|
|
|
await this.smartbucketRef.s3Client.send(command);
|
2024-05-17 16:53:11 +00:00
|
|
|
console.log(`Object '${optionsArg.path}' exists in bucket '${this.name}'.`);
|
|
|
|
return true;
|
|
|
|
} catch (error) {
|
2024-06-17 14:01:35 +00:00
|
|
|
if (error.name === 'NotFound') {
|
2024-05-17 16:53:11 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2019-10-15 17:23:06 +00:00
|
|
|
}
|
2024-05-20 23:22:21 +00:00
|
|
|
|
2024-06-03 19:35:08 +00:00
|
|
|
/**
|
|
|
|
* deletes this bucket
|
|
|
|
*/
|
|
|
|
public async delete() {
|
2024-06-17 14:01:35 +00:00
|
|
|
await this.smartbucketRef.s3Client.send(
|
|
|
|
new plugins.s3.DeleteBucketCommand({ Bucket: this.name })
|
|
|
|
);
|
2024-06-03 19:35:08 +00:00
|
|
|
}
|
|
|
|
|
2024-05-27 10:56:25 +00:00
|
|
|
public async fastStat(pathDescriptor: interfaces.IPathDecriptor) {
|
2024-06-17 14:01:35 +00:00
|
|
|
const checkPath = await helpers.reducePathDescriptorToPath(pathDescriptor);
|
|
|
|
const command = new plugins.s3.HeadObjectCommand({
|
|
|
|
Bucket: this.name,
|
|
|
|
Key: checkPath,
|
|
|
|
});
|
|
|
|
return this.smartbucketRef.s3Client.send(command);
|
2024-05-27 10:56:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public async isDirectory(pathDescriptor: interfaces.IPathDecriptor): Promise<boolean> {
|
2024-06-17 14:01:35 +00:00
|
|
|
const checkPath = await helpers.reducePathDescriptorToPath(pathDescriptor);
|
|
|
|
const command = new plugins.s3.ListObjectsV2Command({
|
|
|
|
Bucket: this.name,
|
|
|
|
Prefix: checkPath,
|
|
|
|
Delimiter: '/',
|
2024-05-27 10:56:25 +00:00
|
|
|
});
|
2024-06-17 14:01:35 +00:00
|
|
|
const response = await this.smartbucketRef.s3Client.send(command);
|
|
|
|
return response.CommonPrefixes.length > 0;
|
2024-06-10 14:47:20 +00:00
|
|
|
}
|
2024-05-27 10:56:25 +00:00
|
|
|
|
|
|
|
public async isFile(pathDescriptor: interfaces.IPathDecriptor): Promise<boolean> {
|
2024-06-17 14:01:35 +00:00
|
|
|
const checkPath = await helpers.reducePathDescriptorToPath(pathDescriptor);
|
|
|
|
const command = new plugins.s3.ListObjectsV2Command({
|
|
|
|
Bucket: this.name,
|
|
|
|
Prefix: checkPath,
|
|
|
|
Delimiter: '/',
|
2024-05-27 10:56:25 +00:00
|
|
|
});
|
2024-06-17 14:01:35 +00:00
|
|
|
const response = await this.smartbucketRef.s3Client.send(command);
|
|
|
|
return response.Contents.length > 0;
|
2024-05-20 23:22:21 +00:00
|
|
|
}
|
2024-11-18 14:07:46 +00:00
|
|
|
|
|
|
|
public async getMagicBytes(optionsArg: { path: string; length: number }): Promise<Buffer> {
|
|
|
|
try {
|
|
|
|
const command = new plugins.s3.GetObjectCommand({
|
|
|
|
Bucket: this.name,
|
|
|
|
Key: optionsArg.path,
|
|
|
|
Range: `bytes=0-${optionsArg.length - 1}`,
|
|
|
|
});
|
|
|
|
const response = await this.smartbucketRef.s3Client.send(command);
|
|
|
|
const chunks = [];
|
|
|
|
const stream = response.Body as any; // SdkStreamMixin includes readable stream
|
|
|
|
|
|
|
|
for await (const chunk of stream) {
|
|
|
|
chunks.push(chunk);
|
|
|
|
}
|
|
|
|
return Buffer.concat(chunks);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(
|
|
|
|
`Error retrieving magic bytes from object at path '${optionsArg.path}' in bucket '${this.name}':`,
|
|
|
|
error
|
|
|
|
);
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
}
|
2019-10-15 12:16:28 +00:00
|
|
|
}
|