@ry-krystal/kicad-converter
Version:
专业的KiCad符号文件与JSON互转工具
342 lines (341 loc) • 8.66 kB
JavaScript
/**
* 通用工具函数模块
* 提供文件操作、路径处理、配置管理等功能
*/
import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync, readdirSync } from 'fs';
import { join, dirname, extname, basename } from 'path';
/**
* 文件工具类
*/
export class FileUtils {
/**
* 安全读取文件
*/
static readFile(filePath, encoding = 'utf8') {
try {
if (!existsSync(filePath)) {
return null;
}
return readFileSync(filePath, encoding);
}
catch {
return null;
}
}
/**
* 安全写入文件
*/
static writeFile(filePath, content, encoding = 'utf8') {
try {
// 确保目录存在
const dir = dirname(filePath);
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true });
}
writeFileSync(filePath, content, encoding);
return true;
}
catch {
return false;
}
}
/**
* 检查文件是否存在
*/
static exists(filePath) {
return existsSync(filePath);
}
/**
* 获取文件信息
*/
static getFileInfo(filePath) {
try {
const stats = statSync(filePath);
return {
size: stats.size,
isFile: stats.isFile(),
isDirectory: stats.isDirectory()
};
}
catch {
return null;
}
}
/**
* 递归查找文件
*/
static findFiles(dir, extensions, recursive = false) {
const results = [];
if (!existsSync(dir)) {
return results;
}
try {
const items = readdirSync(dir);
for (const item of items) {
const fullPath = join(dir, item);
const stat = statSync(fullPath);
if (stat.isDirectory() && recursive) {
results.push(...this.findFiles(fullPath, extensions, recursive));
}
else if (stat.isFile()) {
const ext = extname(item).toLowerCase();
if (extensions.includes(ext)) {
results.push(fullPath);
}
}
}
}
catch {
// 忽略错误,返回已找到的文件
}
return results;
}
}
/**
* 路径工具类
*/
export class PathUtils {
/**
* 标准化路径分隔符
*/
static normalize(path) {
return path.replace(/\\/g, '/');
}
/**
* 获取文件扩展名
*/
static getExtension(filePath) {
return extname(filePath).toLowerCase();
}
/**
* 获取文件名(不含扩展名)
*/
static getNameWithoutExt(filePath) {
return basename(filePath, extname(filePath));
}
/**
* 更改文件扩展名
*/
static changeExtension(filePath, newExt) {
const dir = dirname(filePath);
const name = this.getNameWithoutExt(filePath);
const ext = newExt.startsWith('.') ? newExt : `.${newExt}`;
return join(dir, `${name}${ext}`);
}
/**
* 生成安全的文件名
*/
static sanitizeFilename(filename) {
return filename.replace(/[<>:"/\\|?*]/g, '_').replace(/\s+/g, '_');
}
/**
* 确保目录存在
*/
static ensureDir(dirPath) {
try {
if (!existsSync(dirPath)) {
mkdirSync(dirPath, { recursive: true });
}
return true;
}
catch {
return false;
}
}
}
/**
* 配置管理类
*/
export class ConfigManager {
static configCache = new Map();
/**
* 加载配置文件
*/
static loadConfig(configPath, defaultConfig = {}) {
if (this.configCache.has(configPath)) {
return this.configCache.get(configPath);
}
let config = { ...defaultConfig };
if (existsSync(configPath)) {
try {
const content = readFileSync(configPath, 'utf8');
const loadedConfig = JSON.parse(content);
config = { ...config, ...loadedConfig };
}
catch (error) {
console.warn(`配置文件加载失败: ${configPath}`, error);
}
}
this.configCache.set(configPath, config);
return config;
}
/**
* 保存配置文件
*/
static saveConfig(configPath, config) {
try {
const dir = dirname(configPath);
if (!existsSync(dir)) {
mkdirSync(dir, { recursive: true });
}
const content = JSON.stringify(config, null, 2);
writeFileSync(configPath, content, 'utf8');
// 更新缓存
this.configCache.set(configPath, config);
return true;
}
catch {
return false;
}
}
/**
* 清理配置缓存
*/
static clearCache(configPath) {
if (configPath) {
this.configCache.delete(configPath);
}
else {
this.configCache.clear();
}
}
}
/**
* 日志工具类
*/
export class Logger {
verbose;
quiet;
constructor(verbose = false, quiet = false) {
this.verbose = verbose;
this.quiet = quiet;
}
info(message) {
if (!this.quiet) {
console.log(`ℹ️ ${message}`);
}
}
success(message) {
if (!this.quiet) {
console.log(`✅ ${message}`);
}
}
warn(message) {
if (!this.quiet) {
console.warn(`⚠️ ${message}`);
}
}
error(message) {
console.error(`❌ ${message}`);
}
debug(message) {
if (this.verbose && !this.quiet) {
console.log(`🔍 ${message}`);
}
}
verboseLog(message) {
if (this.verbose && !this.quiet) {
console.log(`📝 ${message}`);
}
}
}
/**
* 性能计时器
*/
export class Timer {
startTime;
marks = new Map();
constructor() {
this.startTime = performance.now();
}
/**
* 设置时间标记
*/
mark(name) {
this.marks.set(name, performance.now());
}
/**
* 获取从开始到现在的时间
*/
elapsed() {
return performance.now() - this.startTime;
}
/**
* 获取两个标记之间的时间
*/
measure(startMark, endMark) {
const start = this.marks.get(startMark);
if (!start)
return 0;
const end = endMark ? this.marks.get(endMark) : performance.now();
if (!end)
return 0;
return end - start;
}
/**
* 格式化时间显示
*/
static formatTime(ms) {
if (ms < 1000) {
return `${ms.toFixed(2)}ms`;
}
else if (ms < 60000) {
return `${(ms / 1000).toFixed(2)}s`;
}
else {
const minutes = Math.floor(ms / 60000);
const seconds = ((ms % 60000) / 1000).toFixed(2);
return `${minutes}m ${seconds}s`;
}
}
}
/**
* 数据验证工具
*/
export class Validator {
/**
* 验证文件路径
*/
static validatePath(path, shouldExist = true) {
if (!path || typeof path !== 'string') {
return { valid: false, message: '路径不能为空' };
}
if (shouldExist && !existsSync(path)) {
return { valid: false, message: `文件或目录不存在: ${path}` };
}
return { valid: true };
}
/**
* 验证文件扩展名
*/
static validateExtension(filename, validExtensions) {
const ext = extname(filename).toLowerCase();
return validExtensions.includes(ext);
}
/**
* 验证JSON格式
*/
static validateJson(content) {
try {
const data = JSON.parse(content);
return { valid: true, data };
}
catch (error) {
return {
valid: false,
error: error instanceof Error ? error.message : 'JSON格式错误'
};
}
}
}
// 导出便捷函数
export const fileUtils = FileUtils;
export const pathUtils = PathUtils;
export const configManager = ConfigManager;
// 创建默认实例
export function createLogger(verbose = false, quiet = false) {
return new Logger(verbose, quiet);
}
export function createTimer() {
return new Timer();
}