UNPKG

@rytass/storages

Version:
134 lines (129 loc) 4.76 kB
'use strict'; var fileConverter = require('@rytass/file-converter'); var stream = require('stream'); var crypto = require('crypto'); 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) { return fileType.fromBuffer(file); } const extensionStream = new stream.PassThrough(); file.pipe(extensionStream); return fileType.fromStream(extensionStream); } async getBufferFilename(buffer) { const extension = await fileType.fromBuffer(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)=>{ if (resolved) return; bufferStorage.push(buffer); const targetBuffer = Buffer.concat(bufferStorage); if (targetBuffer.length >= MIN_BUFFER_LENGTH) { const taskIndex = waitingTasks.length; waitingTasks.push(true); fileType.fromBuffer(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;