@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
JavaScript
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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