t-comm
Version:
专业、稳定、纯粹的工具库
395 lines (392 loc) • 11.9 kB
JavaScript
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import { writeFileSync, readFileSync } from './fs.mjs';
import { getFs } from '../nodejs/fs.mjs';
import { getPath } from '../nodejs/path.mjs';
import { timeStampFormat } from '../time/time.mjs';
import '../nodejs/crypto.mjs';
import '../nodejs/os.mjs';
var LOG_DIR = 'log';
/**
* 内部复制函数,用于复制文件和目录
* @param src - 源路径
* @param dist - 目标路径
* @private
*/
function innerCopy(src, dist) {
// statSync 的结果除了 isFile() 和 isDirectory(),还可能是
// 符号链接(symlink)、块设备、字符设备、FIFO 等
if (!getFs().statSync(src).isDirectory()) {
return;
}
var paths = getFs().readdirSync(src);
paths.forEach(function (p) {
var tSrc = "".concat(src, "/").concat(p);
var tDist = "".concat(dist, "/").concat(p);
var stat = getFs().statSync(tSrc);
if (stat.isFile()) {
// 判断是文件还是目录
writeFileSync(tDist, readFileSync(tSrc));
} else if (stat.isDirectory()) {
innerCopyDir(tSrc, tDist); // 当是目录时,递归复制
}
});
}
/**
* 内部递归复制目录函数
* 复制目录、子目录,及其中的文件
* @param src - 要复制的源目录路径
* @param dist - 复制到的目标目录路径
* @private
*/
function innerCopyDir(src, dist) {
var b = getFs().existsSync(dist);
if (!b) {
mkDirsSync(dist); // 创建目录
}
innerCopy(src, dist);
}
/**
* 递归创建目录(同步方法)
* 如果目录已存在则直接返回,否则递归创建父目录
* @param dirname - 要创建的目录路径
* @returns 创建成功返回 true
* @example
* ```ts
* mkDirsSync('/path/to/new/directory');
* ```
*/
function mkDirsSync(dirname) {
if (getFs().existsSync(dirname)) {
return true;
}
if (mkDirsSync(getPath().dirname(dirname))) {
getFs().mkdirSync(dirname);
return true;
}
return false;
}
/**
* 拷贝目录以及子文件
* 递归复制整个目录结构,包括所有子目录和文件
* @param src - 源目录路径
* @param dist - 目标目录路径
* @param callback - 可选的回调函数,复制完成后执行
* @example
* ```ts
* copyDir('/source/path', '/target/path', () => {
* console.log('复制完成');
* });
* ```
*/
function copyDir(src, dist, callback) {
innerCopyDir(src, dist);
if (callback) {
callback();
}
}
/**
* 删除目录及其所有内容
* 递归删除目录下的所有文件和子目录
* @param tPath - 要删除的目录路径
* @example
* ```ts
* deleteFolder('/path/to/folder');
* ```
*/
function deleteFolder(tPath) {
var files = [];
if (getFs().existsSync(tPath)) {
files = getFs().readdirSync(tPath);
files.forEach(function (file) {
var curPath = "".concat(tPath, "/").concat(file);
if (getFs().statSync(curPath).isDirectory()) {
deleteFolder(curPath);
} else {
getFs().unlinkSync(curPath);
}
});
getFs().rmdirSync(tPath);
}
}
/**
* 递归删除空目录
* 从指定路径开始,递归删除所有空目录(不删除包含文件的目录)
* @param tPath - 要检查和删除的目录路径
* @param level - 当前递归层级,默认为 0(根层级不会被删除)
* @example
* ```ts
* rmEmptyDir('/path/to/check');
* ```
*/
function rmEmptyDir(tPath) {
var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var files = getFs().readdirSync(tPath);
if (files.length > 0) {
var tempFile = 0;
files.forEach(function (file) {
tempFile += 1;
rmEmptyDir("".concat(tPath, "/").concat(file), level + 1);
});
if (tempFile === files.length && level !== 0) {
getFs().rmdirSync(tPath);
}
} else {
level !== 0 && getFs().rmdirSync(tPath);
}
}
/**
* 递归删除文件夹(可配置是否删除文件)
* 递归遍历目录,根据配置决定是否删除文件,并删除空目录
* @param path - 要处理的目录路径
* @param options - 配置选项
* @param options.deleteFile - 是否删除文件,默认为 false
* @param options.log - 是否输出日志,默认为 false
* @example
* ```ts
* // 只删除空目录
* deleteFolderRecursive('/path/to/folder');
*
* // 删除所有文件和目录
* deleteFolderRecursive('/path/to/folder', { deleteFile: true, log: true });
* ```
*/
function deleteFolderRecursive(path) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
deleteFile: false,
log: false
};
var _a, _b;
var deleteFile = (_a = options.deleteFile) !== null && _a !== void 0 ? _a : false;
var log = (_b = options.log) !== null && _b !== void 0 ? _b : false;
if (getFs().existsSync(path)) {
var list = getFs().readdirSync(path);
list.forEach(function (file) {
var curPath = "".concat(path, "/").concat(file);
if (getFs().statSync(curPath).isDirectory()) {
// recurse
deleteFolderRecursive(curPath, options);
} else {
// delete file
if (deleteFile) {
getFs().unlinkSync(curPath);
}
}
});
var remaining = getFs().readdirSync(path);
if (!remaining.length) {
if (log) {
console.log('>>> delete: ', path);
}
getFs().rmdirSync(path);
}
}
}
/**
* 拷贝单个文件
* 将文件从源路径复制到目标路径
* @param from - 源文件路径
* @param to - 目标文件路径
* @returns 写入操作的结果
* @example
* ```ts
* copyFile('/source/file.txt', '/target/file.txt');
* ```
*/
function copyFile(from, to) {
return writeFileSync(to, readFileSync(from));
}
/**
* 递归遍历文件夹,并对每个文件执行回调函数
* 遍历目录树,对每个文件(非目录)执行指定的回调函数
* @param cb - 回调函数,接收文件路径作为参数
* @param tPath - 要遍历的文件夹或文件路径
* @example
* ```ts
* traverseFolder((filePath) => {
* console.log('处理文件:', filePath);
* }, '/path/to/folder');
* ```
*/
function traverseFolder(cb, tPath) {
if (getFs().statSync(tPath).isDirectory()) {
var files = getFs().readdirSync(tPath);
files.forEach(function (file) {
var curPath = getPath().resolve(tPath, file);
// `${tPath}/${file}`;
traverseFolder(cb, curPath);
});
} else {
cb(tPath);
}
}
/**
* 从日志目录读取 JSON 文件
* 读取 ./log 目录下的 JSON 文件内容
* @param file - 文件名(相对于 log 目录)
* @param defaultContent - 文件不存在时返回的默认内容,默认为 '{}'
* @returns JSON 文件内容字符串
* @example
* ```ts
* const content = readJsonLog('data.json', '[]');
* ```
*/
function readJsonLog(file) {
var defaultContent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '{}';
var filePath = "./".concat(LOG_DIR, "/").concat(file);
if (!getFs().existsSync(filePath)) {
createLogDir();
return defaultContent;
}
return readFileSync(filePath) || defaultContent;
}
/**
* 获取 JSON 日志目录的绝对路径
* @returns 日志目录的绝对路径
* @example
* ```ts
* const logDir = getJsonLogDir();
* console.log(logDir); // /path/to/project/log
* ```
*/
function getJsonLogDir() {
return getPath().resolve(process.cwd(), './log');
}
/**
* 将 JSON 对象保存到日志文件
* 将对象序列化为 JSON 并保存到 ./log 目录下
* @param content - 要保存的对象内容
* @param file - 文件名(相对于 log 目录)
* @param needLog - 是否需要保存日志,默认为 true
* @example
* ```ts
* saveJsonToLog({ status: 'success', data: [1, 2, 3] }, 'result.json');
* ```
*/
function saveJsonToLog(content, file) {
var needLog = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
if (!needLog) return;
createLogDir();
writeFileSync("./".concat(LOG_DIR, "/").concat(file), content, true);
}
/**
* 将内容追加保存到日志文件(支持保留历史记录)
* 以数组形式保存多条日志记录,每条记录包含时间戳和数据,支持限制最大记录数
* @param content - 要保存的内容
* @param file - 文件名(相对于 log 目录)
* @param options - 配置选项
* @param options.needLog - 是否需要保存日志,默认为 true
* @param options.max - 最大保留记录数,默认为 10
* @example
* ```ts
* saveJsonToLogMore({ action: 'upload', status: 'success' }, 'history.json', {
* needLog: true,
* max: 20
* });
* ```
*/
function saveJsonToLogMore(content, file, options) {
var _a, _b;
var needLog = (_a = options === null || options === void 0 ? void 0 : options.needLog) !== null && _a !== void 0 ? _a : true;
var max = (_b = options === null || options === void 0 ? void 0 : options.max) !== null && _b !== void 0 ? _b : 10;
if (!needLog) return;
createLogDir();
var filePath = "./log/".concat(file);
var beforeContent = [];
var newContent = [{
logTime: timeStampFormat(Date.now(), 'yyyy-MM-dd hh:mm:ss'),
data: content
}];
if (getFs().existsSync(filePath)) {
try {
beforeContent = readFileSync(filePath, true).logList || [];
} catch (err) {
beforeContent = [];
}
}
if (beforeContent && Array.isArray(beforeContent)) {
var _newContent;
(_newContent = newContent).push.apply(_newContent, _toConsumableArray(beforeContent));
}
newContent = newContent.slice(0, max);
try {
getFs().writeFile(filePath, JSON.stringify({
logList: newContent
}, null, 2), {
encoding: 'utf-8'
}, function () {});
} catch (err) {}
}
/**
* 从日志目录读取并解析 JSON 文件
* 读取 ./log 目录下的 JSON 文件并解析为对象
* @param file - 文件名(相对于 log 目录)
* @returns 解析后的 JSON 对象,解析失败或文件不存在时返回空对象
* @example
* ```ts
* const data = getJsonFromLog('config.json');
* console.log(data);
* ```
*/
function getJsonFromLog(file) {
var filePath = "./".concat(LOG_DIR, "/").concat(file);
var data = {};
if (!getFs().existsSync(filePath)) {
console.log('[getJsonFromLog] no exist');
} else {
var originFile = getFs().readFileSync(filePath, {
encoding: 'utf-8'
});
try {
data = JSON.parse(originFile);
} catch (err) {}
}
return data;
}
/**
* 创建日志目录
* 如果 ./log 目录不存在则创建
* @private
*/
function createLogDir() {
if (!getFs().existsSync("./".concat(LOG_DIR))) {
getFs().mkdirSync("./".concat(LOG_DIR));
}
}
/**
* 从文件路径中提取文件名(不含扩展名)
* @param file - 文件路径
* @returns 不含扩展名的文件名
* @example
* ```ts
* const name = getFileName('/path/to/file.txt');
* console.log(name); // 'file'
* ```
*/
function getFileName(file) {
var basename = getPath().basename(file);
var extname = getPath().extname(file);
var fileName = basename.replace(new RegExp("".concat(extname, "$")), '');
return fileName;
}
/**
* 解析 JSON 字符串为对象
* 安全地解析 JSON 字符串,解析失败时输出错误信息并返回空对象
* @param content - JSON 字符串内容
* @param file - 文件路径(用于错误日志)
* @returns 解析后的对象,解析失败时返回空对象
* @example
* ```ts
* const data = readJson('{"name":"test"}', 'config.json');
* console.log(data); // { name: 'test' }
* ```
*/
function readJson(content, file) {
var data = {};
try {
data = JSON.parse(content);
} catch (e) {
console.error('>>> read json error: ', file);
}
return data;
}
export { copyDir, copyFile, deleteFolder, deleteFolderRecursive, getFileName, getJsonFromLog, getJsonLogDir, mkDirsSync, readJson, readJsonLog, rmEmptyDir, saveJsonToLog, saveJsonToLogMore, traverseFolder };