@dollhousemcp/mcp-server
Version:
DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.
54 lines • 7.28 kB
JavaScript
/**
* FileStorageBackend - IStorageBackend implementation wrapping FileOperationsService.
*
* Delegates all I/O to the existing security-audited FileOperationsService,
* ensuring path validation, atomic reads, and audit logging are preserved.
*/
import * as path from 'path';
export class FileStorageBackend {
fileOps;
constructor(fileOps) {
this.fileOps = fileOps;
}
async listFiles(directory, extension) {
const entries = await this.fileOps.listDirectory(directory);
return entries.filter(name => name.endsWith(extension));
}
async stat(absolutePath) {
const stats = await this.fileOps.stat(absolutePath);
return {
relativePath: path.basename(absolutePath),
absolutePath,
mtimeMs: stats.mtimeMs,
sizeBytes: stats.size,
};
}
async statMany(directory, relativePaths) {
const results = new Map();
const settled = await Promise.allSettled(relativePaths.map(async (relPath) => {
const absPath = path.join(directory, relPath);
const stats = await this.fileOps.stat(absPath);
return {
relativePath: relPath,
absolutePath: absPath,
mtimeMs: stats.mtimeMs,
sizeBytes: stats.size,
};
}));
for (let i = 0; i < settled.length; i++) {
const result = settled[i];
if (result.status === 'fulfilled') {
results.set(relativePaths[i], result.value);
}
// Rejected entries (e.g. file deleted between list and stat) are silently skipped
}
return results;
}
async readFile(absolutePath) {
return this.fileOps.readFile(absolutePath);
}
async directoryExists(directory) {
return this.fileOps.exists(directory);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmlsZVN0b3JhZ2VCYWNrZW5kLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0b3JhZ2UvRmlsZVN0b3JhZ2VCYWNrZW5kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBRUgsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFLN0IsTUFBTSxPQUFPLGtCQUFrQjtJQUNBO0lBQTdCLFlBQTZCLE9BQThCO1FBQTlCLFlBQU8sR0FBUCxPQUFPLENBQXVCO0lBQUcsQ0FBQztJQUUvRCxLQUFLLENBQUMsU0FBUyxDQUFDLFNBQWlCLEVBQUUsU0FBaUI7UUFDbEQsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM1RCxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFJLENBQUMsWUFBb0I7UUFDN0IsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNwRCxPQUFPO1lBQ0wsWUFBWSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDO1lBQ3pDLFlBQVk7WUFDWixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87WUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxJQUFJO1NBQ3RCLENBQUM7SUFDSixDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVEsQ0FBQyxTQUFpQixFQUFFLGFBQXVCO1FBQ3ZELE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUErQixDQUFDO1FBRXZELE1BQU0sT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FDdEMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7WUFDbEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDOUMsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUMvQyxPQUFPO2dCQUNMLFlBQVksRUFBRSxPQUFPO2dCQUNyQixZQUFZLEVBQUUsT0FBTztnQkFDckIsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO2dCQUN0QixTQUFTLEVBQUUsS0FBSyxDQUFDLElBQUk7YUFDUSxDQUFDO1FBQ2xDLENBQUMsQ0FBQyxDQUNILENBQUM7UUFFRixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3hDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMxQixJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssV0FBVyxFQUFFLENBQUM7Z0JBQ2xDLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM5QyxDQUFDO1lBQ0Qsa0ZBQWtGO1FBQ3BGLENBQUM7UUFFRCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVEsQ0FBQyxZQUFvQjtRQUNqQyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRCxLQUFLLENBQUMsZUFBZSxDQUFDLFNBQWlCO1FBQ3JDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDeEMsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBGaWxlU3RvcmFnZUJhY2tlbmQgLSBJU3RvcmFnZUJhY2tlbmQgaW1wbGVtZW50YXRpb24gd3JhcHBpbmcgRmlsZU9wZXJhdGlvbnNTZXJ2aWNlLlxuICpcbiAqIERlbGVnYXRlcyBhbGwgSS9PIHRvIHRoZSBleGlzdGluZyBzZWN1cml0eS1hdWRpdGVkIEZpbGVPcGVyYXRpb25zU2VydmljZSxcbiAqIGVuc3VyaW5nIHBhdGggdmFsaWRhdGlvbiwgYXRvbWljIHJlYWRzLCBhbmQgYXVkaXQgbG9nZ2luZyBhcmUgcHJlc2VydmVkLlxuICovXG5cbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgdHlwZSB7IElTdG9yYWdlQmFja2VuZCB9IGZyb20gJy4vSVN0b3JhZ2VCYWNrZW5kLmpzJztcbmltcG9ydCB0eXBlIHsgU3RvcmFnZUl0ZW1NZXRhZGF0YSB9IGZyb20gJy4vdHlwZXMuanMnO1xuaW1wb3J0IHR5cGUgeyBGaWxlT3BlcmF0aW9uc1NlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9GaWxlT3BlcmF0aW9uc1NlcnZpY2UuanMnO1xuXG5leHBvcnQgY2xhc3MgRmlsZVN0b3JhZ2VCYWNrZW5kIGltcGxlbWVudHMgSVN0b3JhZ2VCYWNrZW5kIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBmaWxlT3BzOiBGaWxlT3BlcmF0aW9uc1NlcnZpY2UpIHt9XG5cbiAgYXN5bmMgbGlzdEZpbGVzKGRpcmVjdG9yeTogc3RyaW5nLCBleHRlbnNpb246IHN0cmluZyk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBjb25zdCBlbnRyaWVzID0gYXdhaXQgdGhpcy5maWxlT3BzLmxpc3REaXJlY3RvcnkoZGlyZWN0b3J5KTtcbiAgICByZXR1cm4gZW50cmllcy5maWx0ZXIobmFtZSA9PiBuYW1lLmVuZHNXaXRoKGV4dGVuc2lvbikpO1xuICB9XG5cbiAgYXN5bmMgc3RhdChhYnNvbHV0ZVBhdGg6IHN0cmluZyk6IFByb21pc2U8U3RvcmFnZUl0ZW1NZXRhZGF0YT4ge1xuICAgIGNvbnN0IHN0YXRzID0gYXdhaXQgdGhpcy5maWxlT3BzLnN0YXQoYWJzb2x1dGVQYXRoKTtcbiAgICByZXR1cm4ge1xuICAgICAgcmVsYXRpdmVQYXRoOiBwYXRoLmJhc2VuYW1lKGFic29sdXRlUGF0aCksXG4gICAgICBhYnNvbHV0ZVBhdGgsXG4gICAgICBtdGltZU1zOiBzdGF0cy5tdGltZU1zLFxuICAgICAgc2l6ZUJ5dGVzOiBzdGF0cy5zaXplLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBzdGF0TWFueShkaXJlY3Rvcnk6IHN0cmluZywgcmVsYXRpdmVQYXRoczogc3RyaW5nW10pOiBQcm9taXNlPE1hcDxzdHJpbmcsIFN0b3JhZ2VJdGVtTWV0YWRhdGE+PiB7XG4gICAgY29uc3QgcmVzdWx0cyA9IG5ldyBNYXA8c3RyaW5nLCBTdG9yYWdlSXRlbU1ldGFkYXRhPigpO1xuXG4gICAgY29uc3Qgc2V0dGxlZCA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgIHJlbGF0aXZlUGF0aHMubWFwKGFzeW5jIChyZWxQYXRoKSA9PiB7XG4gICAgICAgIGNvbnN0IGFic1BhdGggPSBwYXRoLmpvaW4oZGlyZWN0b3J5LCByZWxQYXRoKTtcbiAgICAgICAgY29uc3Qgc3RhdHMgPSBhd2FpdCB0aGlzLmZpbGVPcHMuc3RhdChhYnNQYXRoKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICByZWxhdGl2ZVBhdGg6IHJlbFBhdGgsXG4gICAgICAgICAgYWJzb2x1dGVQYXRoOiBhYnNQYXRoLFxuICAgICAgICAgIG10aW1lTXM6IHN0YXRzLm10aW1lTXMsXG4gICAgICAgICAgc2l6ZUJ5dGVzOiBzdGF0cy5zaXplLFxuICAgICAgICB9IHNhdGlzZmllcyBTdG9yYWdlSXRlbU1ldGFkYXRhO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZXR0bGVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBzZXR0bGVkW2ldO1xuICAgICAgaWYgKHJlc3VsdC5zdGF0dXMgPT09ICdmdWxmaWxsZWQnKSB7XG4gICAgICAgIHJlc3VsdHMuc2V0KHJlbGF0aXZlUGF0aHNbaV0sIHJlc3VsdC52YWx1ZSk7XG4gICAgICB9XG4gICAgICAvLyBSZWplY3RlZCBlbnRyaWVzIChlLmcuIGZpbGUgZGVsZXRlZCBiZXR3ZWVuIGxpc3QgYW5kIHN0YXQpIGFyZSBzaWxlbnRseSBza2lwcGVkXG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBhc3luYyByZWFkRmlsZShhYnNvbHV0ZVBhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMuZmlsZU9wcy5yZWFkRmlsZShhYnNvbHV0ZVBhdGgpO1xuICB9XG5cbiAgYXN5bmMgZGlyZWN0b3J5RXhpc3RzKGRpcmVjdG9yeTogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIHRoaXMuZmlsZU9wcy5leGlzdHMoZGlyZWN0b3J5KTtcbiAgfVxufVxuIl19