@nasriya/cachify
Version:
A lightweight, extensible in-memory caching library for storing anything, with built-in TTL and customizable cache types.
88 lines (87 loc) • 3.07 kB
JavaScript
import atomix from "@nasriya/atomix";
import PersistanceService from "../../../core/persistence/PersistanceService.js";
import { PassThrough } from "stream";
class S3StorageDriver extends PersistanceService {
#_manager;
#_client;
#_PutObjectCommand;
#_GetObjectCommand;
constructor(persistenceManager, configs) {
super('s3', configs);
this.#_manager = persistenceManager;
}
async #_init() {
if (this.#_client) {
return;
}
const moduleName = '@aws-sdk/client-s3';
let mod;
try {
mod = await atomix.runtime.loadModule(moduleName);
}
catch (error) {
const newErr = new Error(`S3 driver requires "${moduleName}". Please install it with "npm i ${moduleName}".`);
newErr.cause = error;
throw newErr;
}
this.#_client = new mod.S3Client(this.configs);
this.#_GetObjectCommand = mod.GetObjectCommand;
this.#_PutObjectCommand = mod.PutObjectCommand;
}
/**
* Uploads a readable stream to the specified S3 bucket.
*
* @throws {Error} Throws an error if initialization fails or the S3 client is not available.
* @returns {Promise<void>} A promise that resolves when the upload is complete.
*/
async backup(...args) {
const [_, backupStream, key] = args;
try {
await this.#_init();
const stream = new PassThrough();
const command = new this.#_PutObjectCommand({
Bucket: this.configs.bucket,
Key: key,
Body: stream
});
const sendPromise = this.#_client.send(command);
await backupStream.streamTo(stream);
await sendPromise;
}
catch (err) {
if (err instanceof Error) {
err.message = `Failed to upload to S3: ${err.message}`;
}
throw err;
}
}
/**
* Downloads an object from the specified S3 bucket.
*
* @throws {Error} Throws an error if initialization fails or the S3 client is not available.
* @returns {Promise<Buffer>} A promise that resolves with the content of the downloaded object.
*/
async restore(...args) {
const [key] = args;
try {
await this.#_init();
const command = new this.#_GetObjectCommand({
Bucket: this.configs.bucket,
Key: key,
});
const response = await this.#_client.send(command);
if (!response.Body) {
throw new Error(`S3 object "${key}" not found`);
}
const restoreStream = this.#_manager.createRestoreStream();
return await restoreStream.streamFrom(response.Body);
}
catch (error) {
if (error instanceof Error) {
error.message = `Failed to download from S3: ${error.message}`;
}
throw error;
}
}
}
export default S3StorageDriver;