@synet/fs
Version:
Robust, battle-tested filesystem abstraction for Node.js
130 lines (129 loc) • 4.18 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnalyticsFileSystem = void 0;
exports.createAnalyticsFileSystem = createAnalyticsFileSystem;
const unit_1 = require("@synet/unit");
/**
* Analytics filesystem that tracks filesystem operations and provides usage statistics
* Wraps any IFileSystem implementation to provide analytics capabilities
*/
class AnalyticsFileSystem {
constructor(baseFileSystem, options = {}) {
this.baseFileSystem = baseFileSystem;
this.options = options;
this.stats = {
stats: { read: 0, write: 0, delete: 0 },
fileReads: [],
};
this.operationCount = 0;
this.eventEmitter = new unit_1.EventEmitter();
this.emitThreshold = options.emitOn ?? 100;
}
/**
* Get current analytics statistics
*/
getStats() {
return {
stats: { ...this.stats.stats },
fileReads: [...this.stats.fileReads],
};
}
/**
* Get the event emitter for analytics events
*/
getEventEmitter() {
return this.eventEmitter;
}
/**
* Record a file operation and check if stats should be emitted
*/
recordOperation(file, action) {
// Update counters
this.stats.stats[action]++;
// Record file access
this.stats.fileReads.push({
file,
timestamp: new Date().toISOString(),
access: action,
});
this.operationCount++;
// Emit stats if threshold reached
if (this.operationCount >= this.emitThreshold) {
this.emitStats();
}
}
/**
* Emit current stats and reset counters
*/
emitStats() {
const currentStats = this.getStats();
this.eventEmitter.emit({
type: "analytics.stats",
data: currentStats,
timestamp: new Date(),
});
// Reset analytics data
this.stats = {
stats: { read: 0, write: 0, delete: 0 },
fileReads: [],
};
this.operationCount = 0;
}
// IFileSystem implementation with analytics tracking
existsSync(path) {
const result = this.baseFileSystem.existsSync(path);
// Note: exists operations are not tracked as read operations
// as they don't actually read file content
return result;
}
readFileSync(path) {
const result = this.baseFileSystem.readFileSync(path);
this.recordOperation(path, "read");
return result;
}
writeFileSync(path, data) {
this.baseFileSystem.writeFileSync(path, data);
this.recordOperation(path, "write");
}
deleteFileSync(path) {
this.baseFileSystem.deleteFileSync(path);
this.recordOperation(path, "delete");
}
deleteDirSync(path) {
this.baseFileSystem.deleteDirSync(path);
// Directory operations are not tracked individually
// Could be extended if needed
}
readDirSync(dirPath) {
const result = this.baseFileSystem.readDirSync(dirPath);
// Directory reads could be tracked if needed
return result;
}
ensureDirSync(path) {
this.baseFileSystem.ensureDirSync(path);
// Directory operations are not tracked individually
}
chmodSync(path, mode) {
this.baseFileSystem.chmodSync(path, mode);
// Permission changes are not tracked as file operations
}
clear(dirPath) {
if (this.baseFileSystem.clear) {
this.baseFileSystem.clear(dirPath);
}
}
}
exports.AnalyticsFileSystem = AnalyticsFileSystem;
/**
* Factory function to create AnalyticsFileSystem with easy access to event emitter
* @param baseFileSystem The underlying filesystem implementation
* @param options Configuration options
* @returns Object containing the analytics filesystem instance and event emitter
*/
function createAnalyticsFileSystem(baseFileSystem, options = {}) {
const instance = new AnalyticsFileSystem(baseFileSystem, options);
return {
instance,
eventEmitter: instance.getEventEmitter(),
};
}