@rytass/storages
Version:
Rytass Utils Storages
135 lines (130 loc) • 4.85 kB
JavaScript
;
var fileConverter = require('@rytass/file-converter');
var stream = require('stream');
var crypto = require('crypto');
var buffer = require('buffer');
var fileType = require('file-type');
class StorageError extends Error {
code;
message;
constructor(code, message){
super(message || ErrorDefaultMessage[code]);
this.code = code;
this.message = message || ErrorDefaultMessage[code];
}
}
var ErrorCode = /*#__PURE__*/ function(ErrorCode) {
ErrorCode["WRITE_FILE_ERROR"] = "101";
ErrorCode["READ_FILE_ERROR"] = "102";
ErrorCode["REMOVE_FILE_ERROR"] = "103";
ErrorCode["UNRECOGNIZED_ERROR"] = "104";
ErrorCode["DIRECTORY_NOT_FOUND"] = "201";
ErrorCode["FILE_NOT_FOUND"] = "202";
return ErrorCode;
}({});
const ErrorDefaultMessage = {
["101"]: 'WRITE_FILE_ERROR',
["102"]: 'READ_FILE_ERROR',
["103"]: 'REMOVE_FILE_ERROR',
["104"]: 'UNRECOGNIZED_ERROR',
["201"]: 'DIRECTORY_NOT_FOUND',
["202"]: 'FILE_NOT_FOUND'
};
const MIN_BUFFER_LENGTH = 16;
class Storage {
converterManager;
hashAlgorithm;
constructor(options){
this.converterManager = new fileConverter.ConverterManager(options?.converters ?? []);
this.hashAlgorithm = options?.hashAlgorithm || 'sha256';
}
getExtension(file) {
if (file instanceof buffer.Buffer) {
return fileType.fileTypeFromBuffer(file);
}
const extensionStream = new stream.PassThrough();
file.pipe(extensionStream);
return fileType.fileTypeFromStream(extensionStream);
}
async getBufferFilename(buffer) {
const extension = await fileType.fileTypeFromBuffer(buffer);
return [
`${crypto.createHash(this.hashAlgorithm).update(buffer).digest('hex')}${extension?.ext ? `.${extension.ext}` : ''}`,
extension?.mime ?? undefined
];
}
getStreamFilename(stream$1) {
return new Promise((resolve, reject)=>{
const hashStream = new stream.PassThrough();
const extensionStream = new stream.PassThrough();
const getStreamHash = new Promise((subResolve)=>{
const hash = crypto.createHash(this.hashAlgorithm);
hashStream.on('data', (buffer)=>{
hash.update(buffer);
});
hashStream.on('end', ()=>{
subResolve(hash.digest('hex'));
});
});
const getStreamFileType = new Promise((subResolve)=>{
let resolved = false;
let isEnd = false;
const bufferStorage = [];
const waitingTasks = [];
extensionStream.on('data', (buffer$1)=>{
if (resolved) return;
bufferStorage.push(buffer$1);
const targetBuffer = buffer.Buffer.concat(bufferStorage);
if (targetBuffer.length >= MIN_BUFFER_LENGTH) {
const taskIndex = waitingTasks.length;
waitingTasks.push(true);
fileType.fileTypeFromBuffer(targetBuffer).then((result)=>{
waitingTasks[taskIndex] = false;
if (!result && !isEnd) return;
resolved = true;
subResolve(result);
});
} else {
waitingTasks.push(false);
}
});
extensionStream.on('end', ()=>{
isEnd = true;
if (waitingTasks.every((task)=>!task) && !resolved) {
resolved = true;
subResolve(undefined);
}
});
});
Promise.all([
getStreamHash,
getStreamFileType
]).then(([filename, extension])=>{
resolve([
`${filename}${extension?.ext ? `.${extension.ext}` : ''}`,
extension?.mime ?? undefined
]);
}).catch(reject);
stream$1.pipe(hashStream).pipe(extensionStream);
});
}
write(_file, _options) {
throw new Error('Method not implemented.');
}
batchWrite(_files, _options) {
throw new Error('Method not implemented.');
}
read(_key, _options) {
throw new Error('Method not implemented.');
}
remove(_key) {
throw new Error('Method not implemented.');
}
isExists(_key) {
throw new Error('Method not implemented.');
}
}
exports.ConverterManager = fileConverter.ConverterManager;
exports.ErrorCode = ErrorCode;
exports.Storage = Storage;
exports.StorageError = StorageError;