177 lines
4.8 KiB
JavaScript
177 lines
4.8 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Simple Cache Manager for Link Validation Results
|
|
* Uses GitHub Actions cache API or local file storage
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const crypto = require('crypto');
|
|
const process = require('process');
|
|
|
|
const CACHE_VERSION = 'v1';
|
|
const CACHE_KEY_PREFIX = 'link-validation';
|
|
const LOCAL_CACHE_DIR = path.join(process.cwd(), '.cache', 'link-validation');
|
|
|
|
/**
|
|
* Simple cache interface
|
|
*/
|
|
class CacheManager {
|
|
constructor(options = {}) {
|
|
this.useGitHubCache =
|
|
options.useGitHubCache !== false && process.env.GITHUB_ACTIONS;
|
|
this.localCacheDir = options.localCacheDir || LOCAL_CACHE_DIR;
|
|
|
|
// Configurable cache TTL - default 30 days, support environment variable
|
|
this.cacheTTLDays =
|
|
options.cacheTTLDays || parseInt(process.env.LINK_CACHE_TTL_DAYS) || 30;
|
|
this.maxAge = this.cacheTTLDays * 24 * 60 * 60 * 1000;
|
|
|
|
if (!this.useGitHubCache) {
|
|
this.ensureLocalCacheDir();
|
|
}
|
|
}
|
|
|
|
ensureLocalCacheDir() {
|
|
if (!fs.existsSync(this.localCacheDir)) {
|
|
fs.mkdirSync(this.localCacheDir, { recursive: true });
|
|
}
|
|
}
|
|
|
|
generateCacheKey(filePath, fileHash) {
|
|
const pathHash = crypto
|
|
.createHash('sha256')
|
|
.update(filePath)
|
|
.digest('hex')
|
|
.substring(0, 8);
|
|
return `${CACHE_KEY_PREFIX}-${CACHE_VERSION}-${pathHash}-${fileHash}`;
|
|
}
|
|
|
|
async get(filePath, fileHash) {
|
|
if (this.useGitHubCache) {
|
|
return await this.getFromGitHubCache(filePath, fileHash);
|
|
} else {
|
|
return await this.getFromLocalCache(filePath, fileHash);
|
|
}
|
|
}
|
|
|
|
async set(filePath, fileHash, results) {
|
|
if (this.useGitHubCache) {
|
|
return await this.setToGitHubCache(filePath, fileHash, results);
|
|
} else {
|
|
return await this.setToLocalCache(filePath, fileHash, results);
|
|
}
|
|
}
|
|
|
|
async getFromGitHubCache(filePath, fileHash) {
|
|
// TODO: This method is a placeholder for GitHub Actions cache integration
|
|
// GitHub Actions cache is handled directly in the workflow via actions/cache
|
|
// This method should either be implemented or removed in future versions
|
|
console.warn(
|
|
'[PLACEHOLDER] getFromGitHubCache: Using placeholder implementation - always returns null'
|
|
);
|
|
return null;
|
|
}
|
|
|
|
async setToGitHubCache(filePath, fileHash, results) {
|
|
// TODO: This method is a placeholder for GitHub Actions cache integration
|
|
// GitHub Actions cache is handled directly in the workflow via actions/cache
|
|
// This method should either be implemented or removed in future versions
|
|
console.warn(
|
|
'[PLACEHOLDER] setToGitHubCache: Using placeholder implementation - always returns true'
|
|
);
|
|
return true;
|
|
}
|
|
|
|
async getFromLocalCache(filePath, fileHash) {
|
|
const cacheKey = this.generateCacheKey(filePath, fileHash);
|
|
const cacheFile = path.join(this.localCacheDir, `${cacheKey}.json`);
|
|
|
|
if (!fs.existsSync(cacheFile)) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
const content = fs.readFileSync(cacheFile, 'utf8');
|
|
const cached = JSON.parse(content);
|
|
|
|
// TTL check using configured cache duration
|
|
const age = Date.now() - new Date(cached.cachedAt).getTime();
|
|
|
|
if (age > this.maxAge) {
|
|
fs.unlinkSync(cacheFile);
|
|
return null;
|
|
}
|
|
|
|
return cached.results;
|
|
} catch (error) {
|
|
// Clean up corrupted cache
|
|
try {
|
|
fs.unlinkSync(cacheFile);
|
|
} catch {
|
|
// Ignore cleanup errors
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async setToLocalCache(filePath, fileHash, results) {
|
|
const cacheKey = this.generateCacheKey(filePath, fileHash);
|
|
const cacheFile = path.join(this.localCacheDir, `${cacheKey}.json`);
|
|
|
|
const cacheData = {
|
|
filePath,
|
|
fileHash,
|
|
results,
|
|
cachedAt: new Date().toISOString(),
|
|
};
|
|
|
|
try {
|
|
fs.writeFileSync(cacheFile, JSON.stringify(cacheData, null, 2));
|
|
return true;
|
|
} catch (error) {
|
|
console.warn(`Cache save failed: ${error.message}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async cleanup() {
|
|
if (this.useGitHubCache) {
|
|
return { removed: 0, note: 'GitHub Actions cache auto-managed' };
|
|
}
|
|
|
|
let removed = 0;
|
|
if (!fs.existsSync(this.localCacheDir)) {
|
|
return { removed };
|
|
}
|
|
|
|
const files = fs.readdirSync(this.localCacheDir);
|
|
|
|
for (const file of files) {
|
|
if (!file.endsWith('.json')) continue;
|
|
|
|
const filePath = path.join(this.localCacheDir, file);
|
|
try {
|
|
const stat = fs.statSync(filePath);
|
|
if (Date.now() - stat.mtime.getTime() > this.maxAge) {
|
|
fs.unlinkSync(filePath);
|
|
removed++;
|
|
}
|
|
} catch {
|
|
// Remove corrupted files
|
|
try {
|
|
fs.unlinkSync(filePath);
|
|
removed++;
|
|
} catch {
|
|
// Ignore errors
|
|
}
|
|
}
|
|
}
|
|
|
|
return { removed };
|
|
}
|
|
}
|
|
|
|
module.exports = CacheManager;
|
|
module.exports.CacheManager = CacheManager; |