UNPKG

@push.rocks/smartfile

Version:

Provides comprehensive tools for efficient file management in Node.js using TypeScript, including handling streams, virtual directories, and various file operations.

373 lines 24.3 kB
import * as plugins from './smartfile.plugins.js'; import * as interpreter from './smartfile.interpreter.js'; import { Smartfile } from './smartfile.classes.smartfile.js'; import * as memory from './smartfile.memory.js'; /*=============================================================== ============================ Checks ============================= ===============================================================*/ /** * * @param filePath * @returns {boolean} */ export const fileExistsSync = (filePath) => { let fileExistsBool = false; try { plugins.fsExtra.readFileSync(filePath); fileExistsBool = true; } catch (err) { fileExistsBool = false; } return fileExistsBool; }; /** * * @param filePath * @returns {any} */ export const fileExists = async (filePath) => { const done = plugins.smartpromise.defer(); plugins.fs.access(filePath, 4, (err) => { err ? done.resolve(false) : done.resolve(true); }); return done.promise; }; /** * Checks if given path points to an existing directory */ export const isDirectory = (pathArg) => { try { return plugins.fsExtra.statSync(pathArg).isDirectory(); } catch (err) { return false; } }; /** * Checks if given path points to an existing directory */ export const isDirectorySync = (pathArg) => { try { return plugins.fsExtra.statSync(pathArg).isDirectory(); } catch (err) { return false; } }; /** * Checks if a given path points to an existing file */ export const isFile = (pathArg) => { return plugins.fsExtra.statSync(pathArg).isFile(); }; /*=============================================================== ============================ FS ACTIONS ========================= ===============================================================*/ /** * copies a file from A to B on the local disk */ export const copy = async (fromArg, toArg) => { const done = plugins.smartpromise.defer(); plugins.fsExtra.copy(fromArg, toArg, {}, (err) => { if (err) { throw new Error(`Could not copy from ${fromArg} to ${toArg}: ${err}`); } done.resolve(true); }); return done.promise; }; /** * copies a file SYNCHRONOUSLY from A to B on the local disk */ export const copySync = (fromArg, toArg) => { plugins.fsExtra.copySync(fromArg, toArg); return true; }; /** * ensures that a directory is in place */ export const ensureDir = async (dirPathArg) => { await plugins.fsExtra.ensureDir(dirPathArg); }; /** * ensures that a directory is in place */ export const ensureDirSync = (dirPathArg) => { plugins.fsExtra.ensureDirSync(dirPathArg); }; /** * ensure an empty directory * @executes ASYNC */ export const ensureEmptyDir = async (dirPathArg) => { await plugins.fsExtra.ensureDir(dirPathArg); await plugins.fsExtra.emptyDir(dirPathArg); }; /** * ensure an empty directory * @executes SYNC */ export const ensureEmptyDirSync = (dirPathArg) => { plugins.fsExtra.ensureDirSync(dirPathArg); plugins.fsExtra.emptyDirSync(dirPathArg); }; /** * ensures that a file is on disk * @param filePath the filePath to ensureDir * @param the fileContent to place into a new file in case it doesn't exist yet * @returns Promise<void> * @exec ASYNC */ export const ensureFile = async (filePathArg, initFileStringArg) => { ensureFileSync(filePathArg, initFileStringArg); }; /** * ensures that a file is on disk * @param filePath the filePath to ensureDir * @param the fileContent to place into a new file in case it doesn't exist yet * @returns Promise<void> * @exec SYNC */ export const ensureFileSync = (filePathArg, initFileStringArg) => { if (fileExistsSync(filePathArg)) { return null; } else { memory.toFsSync(initFileStringArg, filePathArg); } }; /** * removes a file or folder from local disk */ export const remove = async (pathArg) => { await plugins.fsExtra.remove(pathArg); }; /** * removes a file SYNCHRONOUSLY from local disk */ export const removeSync = (pathArg) => { plugins.fsExtra.removeSync(pathArg); }; /** * removes an array of filePaths from disk */ export const removeMany = async (filePathArrayArg) => { const promiseArray = []; for (const filePath of filePathArrayArg) { promiseArray.push(remove(filePath)); } await Promise.all(promiseArray); }; /** * like removeFilePathArray but SYNCHRONOUSLY */ export const removeManySync = (filePathArrayArg) => { for (const filePath of filePathArrayArg) { removeSync(filePath); } }; /*=============================================================== ============================ Write/Read ========================= ===============================================================*/ /** * * @param filePathArg * @param fileTypeArg * @returns {any} */ export const toObjectSync = (filePathArg, fileTypeArg) => { const fileString = plugins.fsExtra.readFileSync(filePathArg, 'utf8'); let fileType; fileTypeArg ? (fileType = fileTypeArg) : (fileType = interpreter.filetype(filePathArg)); return interpreter.objectFile(fileString, fileType); }; /** * reads a file content to a String */ export const toStringSync = (filePath) => { const encoding = plugins.smartmime.getEncoding(filePath); let fileString = plugins.fsExtra.readFileSync(filePath, encoding); if (Buffer.isBuffer(fileString)) { fileString = fileString.toString('binary'); } return fileString; }; export const toBuffer = async (filePath) => { return plugins.fsExtra.readFile(filePath); }; export const toBufferSync = (filePath) => { return plugins.fsExtra.readFileSync(filePath); }; /** * Creates a Readable Stream from a file path. * @param filePath The path to the file. * @returns {fs.ReadStream} */ export const toReadStream = (filePath) => { if (!fileExistsSync(filePath)) { throw new Error(`File does not exist at path: ${filePath}`); } return plugins.fsExtra.createReadStream(filePath); }; export const fileTreeToHash = async (dirPathArg, miniMatchFilter) => { const fileTreeObject = await fileTreeToObject(dirPathArg, miniMatchFilter); let combinedString = ''; for (const smartfile of fileTreeObject) { combinedString += await smartfile.getHash(); } const hash = await plugins.smarthash.sha256FromString(combinedString); return hash; }; /** * creates a smartfile array from a directory * @param dirPathArg the directory to start from * @param miniMatchFilter a minimatch filter of what files to include */ export const fileTreeToObject = async (dirPathArg, miniMatchFilter) => { // handle absolute miniMatchFilter let dirPath; if (plugins.path.isAbsolute(miniMatchFilter)) { dirPath = '/'; } else { dirPath = plugins.smartpath.transform.toAbsolute(dirPathArg); } const fileTree = await listFileTree(dirPath, miniMatchFilter); const smartfileArray = []; for (const filePath of fileTree) { const readPath = (() => { if (!plugins.path.isAbsolute(filePath)) { return plugins.path.join(dirPath, filePath); } else { return filePath; } })(); const fileBuffer = plugins.fs.readFileSync(readPath); // push a read file as Smartfile smartfileArray.push(new Smartfile({ contentBuffer: fileBuffer, base: dirPath, path: filePath, })); } return smartfileArray; }; /** * lists Folders in a directory on local disk * @returns Promise with an array that contains the folder names */ export const listFolders = async (pathArg, regexFilter) => { return listFoldersSync(pathArg, regexFilter); }; /** * lists Folders SYNCHRONOUSLY in a directory on local disk * @returns an array with the folder names as strings */ export const listFoldersSync = (pathArg, regexFilter) => { let folderArray = plugins.fsExtra.readdirSync(pathArg).filter((file) => { return plugins.fsExtra.statSync(plugins.path.join(pathArg, file)).isDirectory(); }); if (regexFilter) { folderArray = folderArray.filter((fileItem) => { return regexFilter.test(fileItem); }); } return folderArray; }; /** * lists Files in a directory on local disk * @returns Promise */ export const listFiles = async (pathArg, regexFilter) => { return listFilesSync(pathArg, regexFilter); }; /** * lists Files SYNCHRONOUSLY in a directory on local disk * @returns an array with the folder names as strings */ export const listFilesSync = (pathArg, regexFilter) => { let fileArray = plugins.fsExtra.readdirSync(pathArg).filter((file) => { return plugins.fsExtra.statSync(plugins.path.join(pathArg, file)).isFile(); }); if (regexFilter) { fileArray = fileArray.filter((fileItem) => { return regexFilter.test(fileItem); }); } return fileArray; }; /** * lists all items (folders AND files) in a directory on local disk * @returns Promise<string[]> */ export const listAllItems = async (pathArg, regexFilter) => { return listAllItemsSync(pathArg, regexFilter); }; /** * lists all items (folders AND files) in a directory on local disk * @returns an array with the folder names as strings * @executes SYNC */ export const listAllItemsSync = (pathArg, regexFilter) => { let allItmesArray = plugins.fsExtra.readdirSync(pathArg).filter((file) => { return plugins.fsExtra.statSync(plugins.path.join(pathArg, file)).isFile(); }); if (regexFilter) { allItmesArray = allItmesArray.filter((fileItem) => { return regexFilter.test(fileItem); }); } return allItmesArray; }; /** * lists a file tree using a miniMatch filter * note: if the miniMatch Filter is an absolute path, the cwdArg will be omitted * @returns Promise<string[]> string array with the absolute paths of all matching files */ export const listFileTree = async (dirPathArg, miniMatchFilter, absolutePathsBool = false) => { // handle absolute miniMatchFilter let dirPath; if (plugins.path.isAbsolute(miniMatchFilter)) { dirPath = '/'; } else { dirPath = dirPathArg; } const options = { cwd: dirPath, nodir: true, dot: true, }; let fileList = await plugins.glob.glob(miniMatchFilter, options); if (absolutePathsBool) { fileList = fileList.map((filePath) => { return plugins.path.resolve(plugins.path.join(dirPath, filePath)); }); } return fileList; }; /** * checks wether a file is ready for processing */ export const waitForFileToBeReady = async (filePathArg) => { if (!plugins.path.isAbsolute(filePathArg)) { filePathArg = plugins.path.resolve(filePathArg); } const limitedArray = new plugins.lik.LimitedArray(3); let fileReady = false; while (!fileReady) { const stats = await plugins.fsExtra.stat(filePathArg); limitedArray.addOne(stats.size); if (limitedArray.array.length < 3 || !(limitedArray.array[0] === limitedArray.array[1] && limitedArray.array[1] === limitedArray.array[2])) { await plugins.smartdelay.delayFor(5000); } else { fileReady = true; } } }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRmaWxlLmZzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnRmaWxlLmZzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFDbEQsT0FBTyxLQUFLLFdBQVcsTUFBTSw0QkFBNEIsQ0FBQztBQUUxRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFFN0QsT0FBTyxLQUFLLE1BQU0sTUFBTSx1QkFBdUIsQ0FBQztBQUNoRDs7aUVBRWlFO0FBRWpFOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxRQUFRLEVBQVcsRUFBRTtJQUNsRCxJQUFJLGNBQWMsR0FBWSxLQUFLLENBQUM7SUFDcEMsSUFBSTtRQUNGLE9BQU8sQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZDLGNBQWMsR0FBRyxJQUFJLENBQUM7S0FDdkI7SUFBQyxPQUFPLEdBQUcsRUFBRTtRQUNaLGNBQWMsR0FBRyxLQUFLLENBQUM7S0FDeEI7SUFDRCxPQUFPLGNBQWMsQ0FBQztBQUN4QixDQUFDLENBQUM7QUFFRjs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHLEtBQUssRUFBRSxRQUFRLEVBQW9CLEVBQUU7SUFDN0QsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQVcsQ0FBQztJQUNuRCxPQUFPLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUU7UUFDckMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2pELENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxJQUFJ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