feat(storage): generalize S3 client and watcher interfaces to storage-oriented naming with backward compatibility

This commit is contained in:
2026-03-14 19:24:36 +00:00
parent 7959fa6296
commit 18bdb5c7c2
15 changed files with 3598 additions and 3202 deletions

View File

@@ -13,12 +13,12 @@ import { BucketWatcher } from './classes.watcher.js';
/**
* The bucket class exposes the basic functionality of a bucket.
* The functions of the bucket alone are enough to
* operate in S3 basic fashion on blobs of data.
* operate on blobs of data in an S3-compatible object store.
*/
export class Bucket {
public static async getBucketByName(smartbucketRef: SmartBucket, bucketNameArg: string): Promise<Bucket> {
const command = new plugins.s3.ListBucketsCommand({});
const buckets = await smartbucketRef.s3Client.send(command);
const buckets = await smartbucketRef.storageClient.send(command);
const foundBucket = buckets.Buckets!.find((bucket) => bucket.Name === bucketNameArg);
if (foundBucket) {
@@ -32,13 +32,13 @@ export class Bucket {
public static async createBucketByName(smartbucketRef: SmartBucket, bucketName: string) {
const command = new plugins.s3.CreateBucketCommand({ Bucket: bucketName });
await smartbucketRef.s3Client.send(command);
await smartbucketRef.storageClient.send(command);
return new Bucket(smartbucketRef, bucketName);
}
public static async removeBucketByName(smartbucketRef: SmartBucket, bucketName: string) {
const command = new plugins.s3.DeleteBucketCommand({ Bucket: bucketName });
await smartbucketRef.s3Client.send(command);
await smartbucketRef.storageClient.send(command);
}
public smartbucketRef: SmartBucket;
@@ -112,7 +112,7 @@ export class Bucket {
Key: reducedPath,
Body: optionsArg.contents,
});
await this.smartbucketRef.s3Client.send(command);
await this.smartbucketRef.storageClient.send(command);
console.log(`Object '${reducedPath}' has been successfully stored in bucket '${this.name}'.`);
const parsedPath = plugins.path.parse(reducedPath);
@@ -172,7 +172,7 @@ export class Bucket {
Bucket: this.name,
Key: optionsArg.path,
});
const response = await this.smartbucketRef.s3Client.send(command);
const response = await this.smartbucketRef.storageClient.send(command);
const replaySubject = new plugins.smartrx.rxjs.ReplaySubject<Buffer>();
// Convert the stream to a format that supports piping
@@ -216,7 +216,7 @@ export class Bucket {
Bucket: this.name,
Key: optionsArg.path,
});
const response = await this.smartbucketRef.s3Client.send(command);
const response = await this.smartbucketRef.storageClient.send(command);
const stream = response.Body as any; // SdkStreamMixin includes readable stream
const duplexStream = new plugins.smartstream.SmartDuplex<Buffer, Buffer>({
@@ -272,7 +272,7 @@ export class Bucket {
Body: optionsArg.readableStream,
Metadata: optionsArg.nativeMetadata,
});
await this.smartbucketRef.s3Client.send(command);
await this.smartbucketRef.storageClient.send(command);
console.log(
`Object '${optionsArg.path}' has been successfully stored in bucket '${this.name}'.`
@@ -297,7 +297,7 @@ export class Bucket {
const targetBucketName = optionsArg.targetBucket ? optionsArg.targetBucket.name : this.name;
// Retrieve current object information to use in copy conditions
const currentObjInfo = await this.smartbucketRef.s3Client.send(
const currentObjInfo = await this.smartbucketRef.storageClient.send(
new plugins.s3.HeadObjectCommand({
Bucket: this.name,
Key: optionsArg.sourcePath,
@@ -319,7 +319,7 @@ export class Bucket {
Metadata: newNativeMetadata,
MetadataDirective: optionsArg.deleteExistingNativeMetadata ? 'REPLACE' : 'COPY',
});
await this.smartbucketRef.s3Client.send(command);
await this.smartbucketRef.storageClient.send(command);
} catch (err) {
console.error('Error updating metadata:', err);
throw err; // rethrow to allow caller to handle
@@ -379,7 +379,7 @@ export class Bucket {
Bucket: this.name,
Key: optionsArg.path,
});
await this.smartbucketRef.s3Client.send(command);
await this.smartbucketRef.storageClient.send(command);
}
/**
@@ -393,7 +393,7 @@ export class Bucket {
Bucket: this.name,
Key: optionsArg.path,
});
await this.smartbucketRef.s3Client.send(command);
await this.smartbucketRef.storageClient.send(command);
console.log(`Object '${optionsArg.path}' exists in bucket '${this.name}'.`);
return true;
} catch (error: any) {
@@ -411,7 +411,7 @@ export class Bucket {
* deletes this bucket
*/
public async delete() {
await this.smartbucketRef.s3Client.send(
await this.smartbucketRef.storageClient.send(
new plugins.s3.DeleteBucketCommand({ Bucket: this.name })
);
}
@@ -422,7 +422,7 @@ export class Bucket {
Bucket: this.name,
Key: checkPath,
});
return this.smartbucketRef.s3Client.send(command);
return this.smartbucketRef.storageClient.send(command);
}
public async isDirectory(pathDescriptor: interfaces.IPathDecriptor): Promise<boolean> {
@@ -432,7 +432,7 @@ export class Bucket {
Prefix: checkPath,
Delimiter: '/',
});
const { CommonPrefixes } = await this.smartbucketRef.s3Client.send(command);
const { CommonPrefixes } = await this.smartbucketRef.storageClient.send(command);
return !!CommonPrefixes && CommonPrefixes.length > 0;
}
@@ -443,7 +443,7 @@ export class Bucket {
Prefix: checkPath,
Delimiter: '/',
});
const { Contents } = await this.smartbucketRef.s3Client.send(command);
const { Contents } = await this.smartbucketRef.storageClient.send(command);
return !!Contents && Contents.length > 0;
}
@@ -454,7 +454,7 @@ export class Bucket {
Key: optionsArg.path,
Range: `bytes=0-${optionsArg.length - 1}`,
});
const response = await this.smartbucketRef.s3Client.send(command);
const response = await this.smartbucketRef.storageClient.send(command);
const chunks: Buffer[] = [];
const stream = response.Body as any; // SdkStreamMixin includes readable stream
@@ -497,7 +497,7 @@ export class Bucket {
ContinuationToken: continuationToken,
});
const response = await this.smartbucketRef.s3Client.send(command);
const response = await this.smartbucketRef.storageClient.send(command);
for (const obj of response.Contents || []) {
if (obj.Key) yield obj.Key;
@@ -531,7 +531,7 @@ export class Bucket {
ContinuationToken: token,
});
const response = await this.smartbucketRef.s3Client.send(command);
const response = await this.smartbucketRef.storageClient.send(command);
for (const obj of response.Contents || []) {
if (obj.Key) subscriber.next(obj.Key);
@@ -646,7 +646,7 @@ export class Bucket {
// Explicitly type the response
const response: plugins.s3.ListObjectsV2Output =
await this.smartbucketRef.s3Client.send(listCommand);
await this.smartbucketRef.storageClient.send(listCommand);
console.log(`Cleaning contents of bucket '${this.name}': Now deleting ${response.Contents?.length} items...`);
@@ -660,7 +660,7 @@ export class Bucket {
},
});
await this.smartbucketRef.s3Client.send(deleteCommand);
await this.smartbucketRef.storageClient.send(deleteCommand);
}
// Update continuation token and truncation status