@rytass/storages-adapter-local
Version:
Rytass Utils Storages local adapter
142 lines (137 loc) • 5.19 kB
JavaScript
'use strict';
var storages = require('@rytass/storages');
var uuid = require('uuid');
var util = require('util');
var path = require('path');
var fs = require('fs');
var promises = require('fs/promises');
var child_process = require('child_process');
// @dev: for *NIX systems
var StorageLocalHelperCommands = /*#__PURE__*/ function(StorageLocalHelperCommands) {
StorageLocalHelperCommands["USED"] = "du -sm __DIR__ | awk '{ print $1 }'";
StorageLocalHelperCommands["FREE"] = "df -m __DIR__ | awk '$3 ~ /[0-9]+/ { print $4 }'";
StorageLocalHelperCommands["TOTAL"] = "df -m __DIR__ | awk '$3 ~ /[0-9]+/ { print $2 }'";
return StorageLocalHelperCommands;
}({});
// @dev: using the
const exec = util.promisify(child_process.exec);
class LocalStorage extends storages.Storage {
directory;
constructor(options){
super(options);
this.directory = options.directory;
if (options.autoMkdir) {
fs.mkdirSync(this.directory, {
recursive: true
});
}
if (!fs.lstatSync(this.directory).isDirectory()) {
throw new storages.StorageError(storages.ErrorCode.DIRECTORY_NOT_FOUND);
}
}
async getUsageInfo() {
const _usage = await this.getFsUsage();
return _usage;
}
// @dev: returns file system usage in 1M-blocks
async getFsUsage() {
const used = Number((await exec(StorageLocalHelperCommands.USED.replace('__DIR__', this.directory))).stdout);
const free = Number((await exec(StorageLocalHelperCommands.FREE.replace('__DIR__', this.directory))).stdout);
const total = Number((await exec(StorageLocalHelperCommands.TOTAL.replace('__DIR__', this.directory))).stdout);
return {
used,
free,
total
};
}
getFileFullPath(key) {
return path.resolve(this.directory, key);
}
checkFileExists(fullPath) {
try {
if (!fs.lstatSync(fullPath).isFile()) {
throw new storages.StorageError(storages.ErrorCode.FILE_NOT_FOUND);
}
} catch (_ex) {
throw new storages.StorageError(storages.ErrorCode.FILE_NOT_FOUND);
}
}
async writeBuffer(buffer, options) {
const convertedBuffer = await this.converterManager.convert(buffer);
const fileInfo = options?.filename || await this.getBufferFilename(buffer);
const filename = Array.isArray(fileInfo) ? fileInfo[0] : fileInfo;
await promises.writeFile(this.getFileFullPath(filename), convertedBuffer);
return {
key: filename
};
}
async writeStream(stream, options) {
const convertedStream = await this.converterManager.convert(stream);
if (options?.filename) {
const writeStream = fs.createWriteStream(this.getFileFullPath(options.filename));
convertedStream.pipe(writeStream);
await new Promise((resolve, reject)=>{
writeStream.on('finish', resolve);
writeStream.on('error', reject);
});
return {
key: options.filename
};
}
const tempFilename = uuid.v4();
const writeStream = fs.createWriteStream(this.getFileFullPath(tempFilename));
convertedStream.pipe(writeStream);
const [filename] = await this.getStreamFilename(convertedStream);
// Wait for the write stream to finish before renaming
await new Promise((resolve, reject)=>{
writeStream.on('finish', resolve);
writeStream.on('error', reject);
});
await promises.rename(this.getFileFullPath(tempFilename), this.getFileFullPath(filename));
return {
key: filename
};
}
readFileBuffer(key) {
const path = this.getFileFullPath(key);
this.checkFileExists(path);
return promises.readFile(path);
}
readFileStream(key) {
const path = this.getFileFullPath(key);
this.checkFileExists(path);
return fs.createReadStream(path);
}
read(key, options) {
if (options?.format === 'buffer') {
return this.readFileBuffer(key);
}
return Promise.resolve(this.readFileStream(key));
}
async write(file, options) {
const convertedFile = await this.converterManager.convert(file);
if (convertedFile instanceof Buffer) {
return this.writeBuffer(convertedFile, options);
}
return this.writeStream(convertedFile, options);
}
batchWrite(files, options) {
return Promise.all(files.map((file, index)=>this.write(file, options?.[index])));
}
remove(key) {
const path = this.getFileFullPath(key);
this.checkFileExists(path);
return promises.unlink(path);
}
async isExists(key) {
const path = this.getFileFullPath(key);
try {
await this.checkFileExists(path);
return true;
} catch (_ex) {
return false;
}
}
}
exports.LocalStorage = LocalStorage;
exports.StorageLocalHelperCommands = StorageLocalHelperCommands;