@mdfriday/foundry
Version:
The core engine of MDFriday. Convert Markdown and shortcodes into fully themed static sites – Hugo-style, powered by TypeScript.
266 lines • 8.76 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.MemoryModuleCache = exports.FsModuleCache = void 0;
exports.newModuleCache = newModuleCache;
exports.newMemoryModuleCache = newMemoryModuleCache;
const type_1 = require("../type");
const log_1 = require("../../../../pkg/log");
const path = __importStar(require("path"));
// Create domain-specific logger for cache operations
const log = (0, log_1.getDomainLogger)('module', { component: 'cache' });
/**
* File system based module cache implementation
*/
class FsModuleCache {
constructor(fs, cacheDir = './module/cache') {
this.fs = fs;
this.cacheDir = cacheDir;
}
/**
* Get module metadata from cache
*/
async get(modulePath) {
try {
const cacheFile = this.getCacheFilePath(modulePath);
const file = await this.fs.open(cacheFile);
const fileInfo = await file.stat();
const buffer = new Uint8Array(fileInfo.size());
await file.read(buffer);
await file.close();
const content = new TextDecoder().decode(buffer);
return JSON.parse(content);
}
catch (error) {
if (error.message?.includes('ENOENT') || error.message?.includes('no such file')) {
log.error(`Cache miss: ${modulePath}`, error);
return null;
}
const message = error instanceof Error ? error.message : String(error);
log.error(`Cache read error for ${modulePath}: ${message}`);
throw new type_1.ModuleError(`Failed to read cache: ${message}`, 'CACHE_READ_FAILED');
}
}
/**
* Set module metadata in cache
*/
async set(modulePath, metadata) {
try {
// Ensure cache directory exists
await this.fs.mkdirAll(this.cacheDir, 0o755);
const cacheFile = this.getCacheFilePath(modulePath);
const content = JSON.stringify(metadata, null, 2);
const buffer = new TextEncoder().encode(content);
const file = await this.fs.create(cacheFile);
await file.write(buffer);
await file.sync();
await file.close();
}
catch (error) {
const message = error instanceof Error ? error.message : String(error);
log.error(`Cache write error for ${modulePath}: ${message}`);
throw new type_1.ModuleError(`Failed to write cache: ${message}`, 'CACHE_WRITE_FAILED');
}
}
/**
* Check if module exists in cache
*/
async has(modulePath) {
try {
const cacheFile = this.getCacheFilePath(modulePath);
await this.fs.stat(cacheFile);
return true;
}
catch (error) {
return false;
}
}
/**
* Delete module from cache
*/
async delete(modulePath) {
try {
const cacheFile = this.getCacheFilePath(modulePath);
await this.fs.remove(cacheFile);
}
catch (error) {
// File not found is not an error for deletion
if (!error.message?.includes('ENOENT') && !error.message?.includes('no such file')) {
const message = error instanceof Error ? error.message : String(error);
log.error(`Cache delete error for ${modulePath}: ${message}`);
throw new type_1.ModuleError(`Failed to delete cache: ${message}`, 'CACHE_DELETE_FAILED');
}
}
}
/**
* Clear all cache
*/
async clear() {
try {
await this.fs.removeAll(this.cacheDir);
}
catch (error) {
// Directory not found is not an error for clearing
if (!error.message?.includes('ENOENT') && !error.message?.includes('no such file')) {
const message = error instanceof Error ? error.message : String(error);
log.error(`Cache clear error: ${message}`);
throw new type_1.ModuleError(`Failed to clear cache: ${message}`, 'CACHE_CLEAR_FAILED');
}
}
}
/**
* Get cache file path for module
*/
getCacheFilePath(modulePath) {
// Convert module path to safe filename
const safeFileName = modulePath
.replace(/[/\\:*?"<>|]/g, '_') // Replace invalid characters
.replace(/^_+|_+$/g, '') // Remove leading/trailing underscores
+ '.json';
return path.join(this.cacheDir, safeFileName);
}
/**
* Get cache directory
*/
getCacheDir() {
return this.cacheDir;
}
/**
* Get cache stats
*/
async getStats() {
try {
const files = await this.listCacheFiles();
let totalSize = 0;
for (const file of files) {
try {
const filePath = path.join(this.cacheDir, file);
const fileInfo = await this.fs.stat(filePath);
totalSize += fileInfo.size();
}
catch (error) {
// Skip files that can't be read
}
}
return {
totalEntries: files.length,
totalSize,
};
}
catch (error) {
return {
totalEntries: 0,
totalSize: 0,
};
}
}
/**
* List all cached modules
*/
async listCached() {
try {
const files = await this.listCacheFiles();
return files.map(file => path.basename(file, '.json').replace(/_/g, '/'));
}
catch (error) {
return [];
}
}
/**
* Helper to list cache files
*/
async listCacheFiles() {
try {
const dir = await this.fs.open(this.cacheDir);
const files = await dir.readdirnames(-1);
await dir.close();
return files.filter(file => file.endsWith('.json'));
}
catch (error) {
return [];
}
}
}
exports.FsModuleCache = FsModuleCache;
/**
* In-memory module cache implementation for testing
*/
class MemoryModuleCache {
constructor() {
this.cache = new Map();
}
async get(modulePath) {
const metadata = this.cache.get(modulePath);
return metadata ? { ...metadata } : null; // Return copy to prevent mutation
}
async set(modulePath, metadata) {
this.cache.set(modulePath, { ...metadata }); // Store copy to prevent mutation
}
async has(modulePath) {
return this.cache.has(modulePath);
}
async delete(modulePath) {
this.cache.delete(modulePath);
}
async clear() {
this.cache.clear();
}
/**
* Get cache size for testing
*/
size() {
return this.cache.size;
}
/**
* Get all keys for testing
*/
keys() {
return Array.from(this.cache.keys());
}
}
exports.MemoryModuleCache = MemoryModuleCache;
/**
* Creates a new file system based module cache
*/
function newModuleCache(fs, cacheDir) {
return new FsModuleCache(fs, cacheDir);
}
/**
* Creates a new in-memory module cache for testing
*/
function newMemoryModuleCache() {
return new MemoryModuleCache();
}
//# sourceMappingURL=cache.js.map