617 lines
12 KiB
JavaScript
617 lines
12 KiB
JavaScript
const fs = require('fs');
|
|
const os = require('os');
|
|
const Path = require('path');
|
|
const XValueTools = require('./x-value.tools');
|
|
|
|
/**
|
|
* required folder names ...
|
|
*/
|
|
const FolderNames = {
|
|
Documents: 'Documents',
|
|
}
|
|
|
|
/**
|
|
* current os path separators ...
|
|
*/
|
|
const PathSeparator = Path.sep;
|
|
|
|
/**
|
|
* current directory ...
|
|
*/
|
|
const CurrentDir = __dirname;
|
|
|
|
//
|
|
//#region Global ...
|
|
/**
|
|
* retrieve a path status ...
|
|
*
|
|
* @param {string} path a path value to check ...
|
|
* @returns an stat object ...
|
|
*/
|
|
function getStatus(path = '') {
|
|
//
|
|
if (!XValueTools.isValidArg(path)) {
|
|
return undefined;
|
|
}
|
|
|
|
//
|
|
return fs.statSync(path);
|
|
}
|
|
|
|
/**
|
|
* retrieve user's Document path ...
|
|
*
|
|
* @returns a path ...
|
|
*/
|
|
function getDocumentsPath() {
|
|
return Path.join(os.homedir(), FolderNames.Documents);
|
|
}
|
|
|
|
/**
|
|
* retrieve user's Document contents ...
|
|
*
|
|
* @returns resources contents as string array ...
|
|
*/
|
|
function getDocumentsContents() {
|
|
return getDirectoryContents(getDocumentsPath());
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Path ...
|
|
/**
|
|
* retrieve the base name of specific address path ...
|
|
*
|
|
* @param {string} path address of file or folder ...
|
|
* @returns string ...
|
|
*/
|
|
function basename(path = '') {
|
|
//
|
|
if (!XValueTools.isValidArg(path)) {
|
|
return '';
|
|
}
|
|
|
|
//
|
|
const result = Path.basename(path);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* join several path segments together ...
|
|
*
|
|
* @param {...string} path path params ...
|
|
* @returns a joined paths ...
|
|
*/
|
|
function joinPath(...path) {
|
|
return Path.join(...path);
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region File ...
|
|
/**
|
|
* determines a path destination is a file or not ...
|
|
*
|
|
* @param {string} path a path value to check ...
|
|
* @returns a boolean value ...
|
|
*/
|
|
function isFileExists(path = '') {
|
|
//
|
|
if (!XValueTools.isValidArg(path)) {
|
|
return false;
|
|
}
|
|
|
|
//
|
|
try {
|
|
const stat = getStatus(path);
|
|
if (!stat) {
|
|
return false;
|
|
}
|
|
|
|
//
|
|
return stat.isFile();
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* remove a file ...
|
|
*
|
|
* @param {string} path a file path ...
|
|
* @returns {Promise<boolean>} action done or not ...
|
|
*/
|
|
function removeFile(path = '') {
|
|
return new Promise((resolve) => {
|
|
//
|
|
if (!isFileExists(path)) {
|
|
resolve(false);
|
|
}
|
|
|
|
//
|
|
fs.unlink(path, (err) => {
|
|
//
|
|
if (err) {
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
//
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* copy a file to destination path ...
|
|
*
|
|
* @param {string} source source file path ...
|
|
* @param {string} dest dest folder path ...
|
|
* @returns {Promise<boolean>} action done or not ...
|
|
*/
|
|
function copyFile(
|
|
source = '',
|
|
dest = ''
|
|
) {
|
|
return new Promise((resolve) => {
|
|
//
|
|
if (
|
|
!isFileExists(source) ||
|
|
!isDirectoryExists(dest)
|
|
) {
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
//
|
|
const destFilePath = Path.join(dest, Path.basename(source));
|
|
fs.copyFile(source, destFilePath, (err) => {
|
|
//
|
|
if (err) {
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
//
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* reading specified file content ...
|
|
*
|
|
* @param {string} path a file path ...
|
|
* @returns {Promise<string>} file content ...
|
|
*/
|
|
function readFile(path = '') {
|
|
return new Promise((resolve) => {
|
|
//
|
|
if (!isFileExists(path)) {
|
|
resolve('');
|
|
return;
|
|
}
|
|
|
|
//
|
|
fs.readFile(path, 'utf8', (err, content) => {
|
|
//
|
|
if (err) {
|
|
resolve(undefined);
|
|
return;
|
|
}
|
|
|
|
//
|
|
resolve(content);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* write content to a file ...
|
|
*
|
|
* @param {string} path a file path ...
|
|
* @param {string} content the content which going to write to the file ...
|
|
* @param {bool} overwrite determines file overwrite if exists ...
|
|
* @returns {Promise<boolean>} action done or not ...
|
|
*/
|
|
function writeFile(
|
|
path = '',
|
|
content = '',
|
|
overwrite = true
|
|
) {
|
|
return new Promise((resolve) => {
|
|
//
|
|
if (isFileExists(path) && !overwrite) {
|
|
//
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Normalize Content ...
|
|
content = XValueTools.isValidArg(content) ?
|
|
content :
|
|
'';
|
|
|
|
//
|
|
fs.writeFile(path, content, (err) => {
|
|
//
|
|
if (err) {
|
|
//
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
//
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* create a file ...
|
|
*
|
|
* @param {string} path file path ...
|
|
* @param {string} fileName file name ...
|
|
* @returns {Promise<boolean>} action done or not ...
|
|
*/
|
|
function createFile(
|
|
path = '',
|
|
fileName = ''
|
|
) {
|
|
return new Promise((resolve) => {
|
|
//
|
|
const filePath = Path.join(path, fileName);
|
|
if (
|
|
isFileExists(filePath) ||
|
|
!XValueTools.isValidArg(path) ||
|
|
!XValueTools.isValidArg(fileName)
|
|
) {
|
|
//
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
//
|
|
fs.writeFile(filePath, '', (err) => {
|
|
//
|
|
if (err) {
|
|
//
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
//
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* remove a file name extension ...
|
|
*
|
|
* @param {string} name
|
|
* @returns {string} name without extension ...
|
|
*/
|
|
function removeFileExtension(name = '') {
|
|
return name.substring(0, name.lastIndexOf('.')) || name;
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
//#region Directory ...
|
|
/**
|
|
* create a directory ...
|
|
*
|
|
* @param {string} path destination path including dir name ...
|
|
* @param {boolean} recursive create directories recursively ...
|
|
* @returns action done or not ...
|
|
*/
|
|
function createDirectory(
|
|
path = '',
|
|
recursive = true
|
|
) {
|
|
//
|
|
let result = false;
|
|
|
|
//
|
|
if (
|
|
isDirectoryExists(path) ||
|
|
!XValueTools.isValidArg(path)
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
//
|
|
try {
|
|
//
|
|
fs.mkdirSync(path, { recursive: recursive });
|
|
result = true;
|
|
return result;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* remove a directory ...
|
|
*
|
|
* @param {string} path destination path including dir name ...
|
|
* @param {boolean} recursive removes directories recursively ...
|
|
* @returns {Promise<boolean>} action done or not ...
|
|
*/
|
|
function removeDirectory(
|
|
path = '',
|
|
recursive = false
|
|
) {
|
|
return new Promise((resolve) => {
|
|
//
|
|
if (!isDirectoryExists(path)) {
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
//
|
|
fs.rm(path, {
|
|
recursive
|
|
}, (err) => {
|
|
//
|
|
if (err) {
|
|
resolve(false);
|
|
return;
|
|
}
|
|
|
|
//
|
|
resolve(true);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* determines a path destination is a directory or not ...
|
|
*
|
|
* @param {string} path a folder path ...
|
|
* @returns represent destnation path is Directory or not ...
|
|
*/
|
|
function isDirectoryExists(path = '') {
|
|
//
|
|
if (!XValueTools.isValidArg(path)) {
|
|
return false;
|
|
}
|
|
|
|
//
|
|
try {
|
|
//
|
|
const isExists = fs.existsSync(path);
|
|
if (!isExists) {
|
|
return false;
|
|
}
|
|
|
|
//
|
|
const stat = getStatus(path);
|
|
if (!stat) {
|
|
return false;
|
|
}
|
|
|
|
//
|
|
const result = stat.isDirectory();
|
|
return result;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* retrieve a directory content ...
|
|
*
|
|
* @param {string} path a folder path ...
|
|
* @returns {Promise<string[]>} a collection of folder files ...
|
|
*/
|
|
function getDirectoryContents(path = '') {
|
|
return new Promise((resolve) => {
|
|
//
|
|
if (!isDirectoryExists(path)) {
|
|
resolve([]);
|
|
return;
|
|
}
|
|
|
|
//
|
|
fs.readdir(path, (err, content) => {
|
|
//
|
|
if (err) {
|
|
resolve([]);
|
|
return;
|
|
}
|
|
|
|
//
|
|
resolve(content);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* retrieve a directory files ...
|
|
*
|
|
* @param {string} path a folder path ...
|
|
* @returns {Promise<string[]>} a collection of folder files ...
|
|
*/
|
|
function getDirectoryFiles(
|
|
path = '',
|
|
containsHiddenFiles = false
|
|
) {
|
|
return new Promise((resolve) => {
|
|
//
|
|
if (!isDirectoryExists(path)) {
|
|
resolve([]);
|
|
return;
|
|
}
|
|
|
|
//
|
|
fs.readdir(path, (err, content) => {
|
|
//
|
|
if (err) {
|
|
resolve([]);
|
|
return;
|
|
}
|
|
|
|
//
|
|
if (!containsHiddenFiles) {
|
|
content = content.filter(c => !c.startsWith('.'))
|
|
}
|
|
|
|
//
|
|
const result = [];
|
|
content
|
|
.forEach(c => {
|
|
//
|
|
const cPath = Path.join(path, c);
|
|
if (isFileExists(cPath)) {
|
|
result.push(c);
|
|
}
|
|
});
|
|
|
|
//
|
|
resolve(result);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* retrieve a directory folders ...
|
|
*
|
|
* @param {string} path a folder path ...
|
|
* @returns {Promise<string[]>} a collection of folder names ...
|
|
*/
|
|
function getDirectoryFolders(path = '') {
|
|
return new Promise((resolve) => {
|
|
//
|
|
if (!isDirectoryExists(path)) {
|
|
resolve([]);
|
|
return;
|
|
}
|
|
|
|
//
|
|
fs.readdir(path, (err, content) => {
|
|
//
|
|
if (err) {
|
|
resolve([]);
|
|
return;
|
|
}
|
|
|
|
//
|
|
const result = [];
|
|
content.forEach(c => {
|
|
//
|
|
const cPath = Path.join(path, c);
|
|
if (isDirectoryExists(cPath)) {
|
|
result.push(c);
|
|
}
|
|
});
|
|
|
|
//
|
|
resolve(result);
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* copy a folder with all of it's content to dest ...
|
|
*
|
|
* @param {string} source source folder path ...
|
|
* @param {string} dest dest folder path ...
|
|
* @returns {Promise<boolean>} action done or not ...
|
|
*/
|
|
async function copyFolder(
|
|
source = '',
|
|
dest = ''
|
|
) {
|
|
//
|
|
if (
|
|
!isDirectoryExists(source) ||
|
|
!XValueTools.isValidArg(dest) ||
|
|
!XValueTools.isValidArg(source)
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
//
|
|
const folderName = Path.basename(source);
|
|
const destPath = Path.join(dest, folderName);
|
|
|
|
//
|
|
// Create Dest Path folder if not exists ...
|
|
if (!isDirectoryExists(destPath)) {
|
|
//
|
|
let result = createDirectory(destPath, true);
|
|
if (!result) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Files ...
|
|
const files = await getDirectoryFiles(source);
|
|
if (files && files.constructor === Array && files.length > 0) {
|
|
//
|
|
const filesPromises = files.map(file => copyFile(Path.join(source, file), destPath));
|
|
const filesResult = (await Promise.all(filesPromises)).every(r => !!r);
|
|
if (!filesResult) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Folders ...
|
|
const folders = await getDirectoryFolders(source);
|
|
if (folders && folders.constructor === Array && folders.length > 0) {
|
|
//
|
|
const folderPromises = folders.map(folder => copyFolder(Path.join(source, folder), destPath));
|
|
const filesResult = (await Promise.all(folderPromises)).every(r => !!r);
|
|
if (!filesResult) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//
|
|
return true;
|
|
}
|
|
//#endregion
|
|
|
|
//
|
|
// Module Exports ...
|
|
module.exports = {
|
|
//
|
|
CurrentDir,
|
|
FolderNames,
|
|
PathSeparator,
|
|
|
|
//
|
|
getStatus,
|
|
getDocumentsPath,
|
|
getDocumentsContents,
|
|
|
|
//
|
|
basename,
|
|
joinPath,
|
|
|
|
//
|
|
copyFile,
|
|
readFile,
|
|
writeFile,
|
|
createFile,
|
|
removeFile,
|
|
isFileExists,
|
|
removeFileExtension,
|
|
|
|
//
|
|
copyFolder,
|
|
createDirectory,
|
|
removeDirectory,
|
|
createDirectory,
|
|
removeDirectory,
|
|
isDirectoryExists,
|
|
isDirectoryExists,
|
|
getDirectoryFiles,
|
|
getDirectoryFolders,
|
|
getDirectoryContents,
|
|
} |