wiki/patches/s3.driver.js
vickytechkey 1f12f0338e
Some checks failed
Deploy Docmost Wiki / Deploy to cisystem (push) Failing after 4s
feat: configure docmost deployment for cisystem with s3 wikimedia prefix and forgejo workflows
2026-09-12 11:36:56 +05:30

193 lines
6.5 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.S3Driver = void 0;
const interfaces_1 = require("../interfaces");
const client_s3_1 = require("@aws-sdk/client-s3");
const storage_utils_1 = require("../storage.utils");
const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
const helpers_1 = require("../../../common/helpers");
const lib_storage_1 = require("@aws-sdk/lib-storage");
const common_1 = require("@nestjs/common");
const S3_MAX_SOCKETS = parseInt(process.env.AWS_S3_MAX_SOCKETS) || 200;
const S3_PREFIX = process.env.AWS_S3_PREFIX ? process.env.AWS_S3_PREFIX.replace(/^\/+/, '').replace(/\/?$/, '/') : '';
function prefixKey(filePath) {
if (!S3_PREFIX) return filePath;
const cleanPath = filePath.replace(/^\/+/, '');
return cleanPath.startsWith(S3_PREFIX) ? cleanPath : `${S3_PREFIX}${cleanPath}`;
}
class S3Driver {
constructor(config) {
this.config = {
...config,
requestHandler: {
httpAgent: { maxSockets: S3_MAX_SOCKETS },
httpsAgent: { maxSockets: S3_MAX_SOCKETS },
},
};
this.s3Client = new client_s3_1.S3Client(this.config);
}
async upload(filePath, file) {
try {
const key = prefixKey(filePath);
const contentType = (0, helpers_1.getMimeType)(filePath);
const upload = new lib_storage_1.Upload({
client: this.s3Client,
params: {
Bucket: this.config.bucket,
Key: key,
Body: file,
ContentType: contentType,
},
});
await upload.done();
}
catch (err) {
common_1.Logger.error(err);
throw new Error(`Failed to upload file: ${err.message}`);
}
}
async uploadStream(filePath, file, options) {
let clientToUse = this.s3Client;
let shouldDestroyClient = false;
if (options?.recreateClient) {
clientToUse = new client_s3_1.S3Client(this.config);
shouldDestroyClient = true;
}
try {
const key = prefixKey(filePath);
const contentType = (0, helpers_1.getMimeType)(filePath);
const upload = new lib_storage_1.Upload({
client: clientToUse,
params: {
Bucket: this.config.bucket,
Key: key,
Body: file,
ContentType: contentType,
},
});
await upload.done();
}
catch (err) {
common_1.Logger.error(err);
throw new Error(`Failed to upload file: ${err.message}`);
}
finally {
if (shouldDestroyClient && clientToUse) {
clientToUse.destroy();
}
}
}
async copy(fromFilePath, toFilePath) {
try {
const fromKey = prefixKey(fromFilePath);
const toKey = prefixKey(toFilePath);
if (await this.exists(fromFilePath)) {
await this.s3Client.send(new client_s3_1.CopyObjectCommand({
Bucket: this.config.bucket,
CopySource: `${this.config.bucket}/${fromKey}`,
Key: toKey,
}));
}
}
catch (err) {
throw new Error(`Failed to copy file: ${err.message}`);
}
}
async read(filePath) {
try {
const key = prefixKey(filePath);
const command = new client_s3_1.GetObjectCommand({
Bucket: this.config.bucket,
Key: key,
});
const response = await this.s3Client.send(command);
return (0, storage_utils_1.streamToBuffer)(response.Body);
}
catch (err) {
throw new Error(`Failed to read file from S3: ${err.message}`);
}
}
async readStream(filePath) {
try {
const key = prefixKey(filePath);
const command = new client_s3_1.GetObjectCommand({
Bucket: this.config.bucket,
Key: key,
});
const response = await this.s3Client.send(command);
return response.Body;
}
catch (err) {
throw new Error(`Failed to read file from S3: ${err.message}`);
}
}
async readRangeStream(filePath, range) {
try {
const key = prefixKey(filePath);
const command = new client_s3_1.GetObjectCommand({
Bucket: this.config.bucket,
Key: key,
Range: `bytes=${range.start}-${range.end}`,
});
const response = await this.s3Client.send(command);
return response.Body;
}
catch (err) {
throw new Error(`Failed to read file from S3: ${err.message}`);
}
}
async exists(filePath) {
try {
const key = prefixKey(filePath);
const command = new client_s3_1.HeadObjectCommand({
Bucket: this.config.bucket,
Key: key,
});
await this.s3Client.send(command);
return true;
}
catch (err) {
if (err instanceof client_s3_1.NoSuchKey) {
return false;
}
throw err;
}
}
getUrl(filePath) {
const key = prefixKey(filePath);
return `${this.config.baseUrl ?? this.config.endpoint}/${this.config.bucket}/${key}`;
}
async getSignedUrl(filePath, expiresIn) {
const key = prefixKey(filePath);
const command = new client_s3_1.GetObjectCommand({
Bucket: this.config.bucket,
Key: key,
});
return await (0, s3_request_presigner_1.getSignedUrl)(this.s3Client, command, { expiresIn });
}
async delete(filePath) {
try {
const key = prefixKey(filePath);
const command = new client_s3_1.DeleteObjectCommand({
Bucket: this.config.bucket,
Key: key,
});
await this.s3Client.send(command);
}
catch (err) {
throw new Error(`Error deleting file ${filePath} from S3. ${err.message}`);
}
}
getDriver() {
return this.s3Client;
}
getDriverName() {
return interfaces_1.StorageOption.S3;
}
getConfig() {
return this.config;
}
}
exports.S3Driver = S3Driver;