@typecad/kicad-symbols
Version:
Intelligent fuzzy search for KiCad symbols with CLI interface
266 lines • 8.86 kB
JavaScript
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