Files
parsshop-back/dist/modules/storage/storage.service.js
2026-03-26 12:25:46 +03:00

136 lines
5.5 KiB
JavaScript

"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var StorageService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.StorageService = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("@nestjs/config");
const crypto_1 = require("crypto");
const Minio = require("minio");
let StorageService = StorageService_1 = class StorageService {
configService;
logger = new common_1.Logger(StorageService_1.name);
client;
publicBucket;
privateBucket;
publicUrl;
constructor(configService) {
this.configService = configService;
this.client = new Minio.Client({
endPoint: this.configService.getOrThrow('minio.endpoint'),
port: this.configService.get('minio.port', 9000),
useSSL: this.configService.get('minio.useSsl', false),
accessKey: this.configService.getOrThrow('minio.accessKey'),
secretKey: this.configService.getOrThrow('minio.secretKey'),
});
this.publicBucket = this.configService.getOrThrow('minio.publicBucket');
this.privateBucket = this.configService.getOrThrow('minio.privateBucket');
this.publicUrl = this.configService.get('minio.publicUrl');
}
async onModuleInit() {
await this.ensureBucket(this.publicBucket, true);
await this.ensureBucket(this.privateBucket, false);
}
async uploadPublicFile(file, folder = 'products') {
return this.upload(file, this.publicBucket, folder);
}
async uploadPrivateFile(file, folder = 'products') {
return this.upload(file, this.privateBucket, folder);
}
async deleteFile(bucket, objectName) {
try {
await this.client.removeObject(bucket, objectName);
}
catch (error) {
this.logger.warn(`Failed to delete object ${bucket}/${objectName}: ${error instanceof Error ? error.message : 'unknown error'}`);
}
}
async deletePublicFileByUrl(fileUrl) {
if (!fileUrl) {
return;
}
const objectName = this.extractObjectName(fileUrl, this.publicBucket);
if (objectName) {
await this.deleteFile(this.publicBucket, objectName);
}
}
extractObjectName(fileUrl, bucket) {
if (!fileUrl) {
return null;
}
try {
const parsedUrl = new URL(fileUrl);
const prefix = `/${bucket}/`;
const path = parsedUrl.pathname.startsWith(prefix)
? parsedUrl.pathname.slice(prefix.length)
: parsedUrl.pathname.replace(/^\//, '');
return decodeURIComponent(path);
}
catch {
return null;
}
}
async upload(file, bucket, folder) {
if (!file) {
throw new common_1.InternalServerErrorException('File upload payload is empty');
}
const objectName = `${folder}/${(0, crypto_1.randomUUID)()}-${file.originalname.replace(/\s+/g, '-')}`;
try {
await this.client.putObject(bucket, objectName, file.buffer, file.size, {
'Content-Type': file.mimetype,
});
}
catch (error) {
throw new common_1.InternalServerErrorException(`File upload failed: ${error instanceof Error ? error.message : 'unknown error'}`);
}
return {
bucket,
objectName,
url: this.buildPublicUrl(bucket, objectName),
};
}
async ensureBucket(bucketName, makePublic) {
const exists = await this.client.bucketExists(bucketName);
if (!exists) {
await this.client.makeBucket(bucketName);
}
if (makePublic) {
await this.client.setBucketPolicy(bucketName, JSON.stringify({
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: { AWS: ['*'] },
Action: ['s3:GetObject'],
Resource: [`arn:aws:s3:::${bucketName}/*`],
},
],
}));
}
}
buildPublicUrl(bucket, objectName) {
if (this.publicUrl) {
return `${this.publicUrl.replace(/\/$/, '')}/${bucket}/${objectName}`;
}
const protocol = this.configService.get('minio.useSsl', false)
? 'https'
: 'http';
const endpoint = this.configService.getOrThrow('minio.endpoint');
const port = this.configService.get('minio.port', 9000);
return `${protocol}://${endpoint}:${port}/${bucket}/${objectName}`;
}
};
exports.StorageService = StorageService;
exports.StorageService = StorageService = StorageService_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [config_1.ConfigService])
], StorageService);
//# sourceMappingURL=storage.service.js.map