UNPKG

@typecad/kicad-symbols

Version:

Intelligent fuzzy search for KiCad symbols with CLI interface

266 lines 8.86 kB
import { promises as fs } from 'fs'; import { DateBasedCacheManager } from './DateBasedCacheManager.js'; import { KiCadLocalDataProcessor } from './KiCadLocalDataProcessor.js'; import { KiCadSymbolConverter } from './KiCadSymbolConverter.js'; import { CacheUtils } from '../utils/CacheUtils.js'; /** * Data source modes for the DataManager */ export var DataSourceMode; (function (DataSourceMode) { /** Process local KiCad symbol files */ DataSourceMode["LOCAL_FILES"] = "local_files"; })(DataSourceMode || (DataSourceMode = {})); /** * Default DataManager configuration */ const DEFAULT_CONFIG = { mode: DataSourceMode.LOCAL_FILES, enableProgress: false }; /** * Manages component data including caching and parsing * Supports local file processing mode only */ export class DataManager { localDataPath; cacheManager; localProcessor; config; cachedComponents = null; currentMode = DataSourceMode.LOCAL_FILES; useSharedCache; /** * Creates a new DataManager * @param localDataPath Local path to save the data file (ignored if useSharedCache is true) * @param cacheDir Directory to store cache files (ignored if useSharedCache is true) * @param cacheExpirationHours Number of hours before cache expires * @param config Optional configuration for data source mode and options * @param useSharedCache Whether to use shared temp directory for cache files */ constructor(localDataPath = 'kicad-symbols-data.json', cacheDir = '.', cacheExpirationHours = 24, config = {}, useSharedCache = true) { this.useSharedCache = useSharedCache; this.localDataPath = localDataPath; this.config = { ...DEFAULT_CONFIG, ...config }; this.currentMode = DataSourceMode.LOCAL_FILES; this.cacheManager = new DateBasedCacheManager(cacheDir, cacheExpirationHours, useSharedCache); this.localProcessor = new KiCadLocalDataProcessor({ customSymbolsPath: this.config.customSymbolsPath, enableProgress: this.config.enableProgress }); } /** * Gets the cache file path, using shared cache directory if enabled */ async getCacheFilePath() { if (this.useSharedCache) { return await CacheUtils.getDefaultCacheFilePath(); } return this.localDataPath; } /** * Ensures that component data is available and up-to-date */ async ensureDataAvailable() { try { // Always use local files mode this.currentMode = DataSourceMode.LOCAL_FILES; await this.ensureLocalDataAvailable(); } catch (error) { console.error('Failed to ensure data availability:', error); throw error; } } /** * Ensures local data is available and up-to-date */ async ensureLocalDataAvailable() { try { // Check if we have valid cached data if (await this.isLocalCacheValid()) { console.log('Using cached local KiCad symbols data.'); return; } // Check if local symbols are available const symbolsPath = await this.getLocalSymbolsPath(); if (!symbolsPath) { throw new Error('No local KiCad symbols found. Please ensure KiCad symbols are installed.'); } console.log('Processing local KiCad symbols...'); // Process local symbols const extractedSymbols = await this.localProcessor.processLocalSymbols(); // Convert to ComponentRecord format const converter = new KiCadSymbolConverter(); const components = converter.convertSymbolsToComponentRecords(extractedSymbols); // Save processed data await this.saveDataToFile(components); // Update cache timestamp await this.cacheManager.writeTimestamp(); console.log(`Successfully processed ${components.length} symbols from local files.`); } catch (error) { console.error('Failed to process local symbols:', error); throw error; } } /** * Gets component data from the cache or processes local files */ async getCsvData() { if (this.cachedComponents) { return this.cachedComponents; } await this.ensureDataAvailable(); try { this.cachedComponents = await this.loadDataFromFile(); return this.cachedComponents; } catch (error) { console.error('Failed to load component data:', error); throw error; } } /** * Checks if the local cache is valid */ async isDataStale() { return !(await this.isLocalCacheValid()); } /** * Saves component data to a JSON file */ async saveDataToFile(components) { try { const cacheFilePath = await this.getCacheFilePath(); const data = JSON.stringify(components, null, 2); await fs.writeFile(cacheFilePath, data, 'utf8'); } catch (error) { console.error('Failed to save data to file:', error); throw error; } } /** * Loads component data from the JSON file */ async loadDataFromFile() { try { const cacheFilePath = await this.getCacheFilePath(); const data = await fs.readFile(cacheFilePath, 'utf8'); return JSON.parse(data); } catch (error) { console.error('Failed to load data from file:', error); throw error; } } /** * Gets the current data source mode */ getCurrentMode() { return this.currentMode; } /** * Checks if local KiCad symbols are available */ async areLocalSymbolsAvailable() { const symbolsPath = await this.getLocalSymbolsPath(); return symbolsPath !== undefined; } /** * Gets the path to local KiCad symbols */ async getLocalSymbolsPath() { try { return await this.localProcessor.getSymbolsPath(); } catch (error) { return undefined; } } /** * Forces a refresh of the data by clearing cache and reprocessing */ async forceRefresh() { console.log('Forcing data refresh...'); // Clear cached data this.cachedComponents = null; // Clear cache timestamp await this.cacheManager.deleteTimestamp(); // Reprocess data await this.ensureDataAvailable(); } /** * Gets processing statistics from the local processor */ getProcessingStatistics() { return this.localProcessor.getStatistics(); } /** * Gets a summary of processing results */ getProcessingSummary() { return this.localProcessor.getProcessingSummary(); } /** * Checks if the local cache is valid */ async isLocalCacheValid() { try { // Check if cache file exists and is not expired if (await this.cacheManager.isCacheStale()) { return false; } // Check if data file exists const cacheFilePath = await this.getCacheFilePath(); if (!(await this.fileExists(cacheFilePath))) { return false; } // Check if local symbols have been updated since last cache const symbolsPath = await this.getLocalSymbolsPath(); if (!symbolsPath) { return false; } const cacheTimestamp = await this.cacheManager.readTimestamp(); if (!cacheTimestamp) { return false; } // Check if symbol files are newer than cache if (await this.hasNewerSymbolFiles(symbolsPath, cacheTimestamp)) { return false; } return true; } catch (error) { console.error('Error checking cache validity:', error); return false; } } /** * Checks if symbol files are newer than the cache timestamp */ async hasNewerSymbolFiles(symbolsPath, cacheTimestamp) { try { const stats = await fs.stat(symbolsPath); return stats.mtime > cacheTimestamp; } catch (error) { console.error('Error checking file timestamps:', error); return false; } } /** * Checks if a file exists */ async fileExists(filePath) { try { await fs.access(filePath); return true; } catch { return false; } } } //# sourceMappingURL=DataManager.js.map