ripple-ai-detector
Version:
🌊 Ripple AI Bug Detector - Built by an AI that knows its flaws. Catch AI-generated bugs before you commit.
173 lines • 6.13 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UsageTracker = void 0;
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const os_1 = __importDefault(require("os"));
class UsageTracker {
usageFile;
defaultLimits = {
free: 50,
pro: -1, // unlimited
team: -1, // unlimited
enterprise: -1 // unlimited
};
constructor() {
// Store usage data in user's home directory
const rippleDir = path_1.default.join(os_1.default.homedir(), '.ripple');
this.usageFile = path_1.default.join(rippleDir, 'usage.json');
}
// Get current usage information
async getUsage() {
const data = await this.loadUsageData();
const currentMonth = this.getCurrentMonth();
// Reset if new month
if (data.currentMonth !== currentMonth) {
data.currentMonth = currentMonth;
data.validationsThisMonth = 0;
data.lastReset = new Date().toISOString();
data.events = [];
await this.saveUsageData(data);
}
const limit = this.defaultLimits[data.plan];
return {
current: data.validationsThisMonth,
limit: limit === -1 ? 999999 : limit, // Show large number for unlimited
resetDate: this.getNextResetDate(),
plan: data.plan
};
}
// Check if user can perform validation
async canValidate() {
const usage = await this.getUsage();
// Pro and above have unlimited validations
if (usage.plan !== 'free') {
return true;
}
return usage.current < usage.limit;
}
// Track a validation event
async trackValidation(filesCount, aiDetected, timeMs = 0) {
const data = await this.loadUsageData();
const currentMonth = this.getCurrentMonth();
// Reset if new month
if (data.currentMonth !== currentMonth) {
data.currentMonth = currentMonth;
data.validationsThisMonth = 0;
data.lastReset = new Date().toISOString();
data.events = [];
}
// Increment validation count
data.validationsThisMonth++;
// Add event
const event = {
timestamp: new Date().toISOString(),
filesCount,
aiDetected,
issuesFound: 0, // Will be updated by caller if needed
timeMs
};
data.events.push(event);
// Keep only last 100 events
if (data.events.length > 100) {
data.events = data.events.slice(-100);
}
await this.saveUsageData(data);
}
// Update plan (when user upgrades)
async updatePlan(plan, licenseKey) {
const data = await this.loadUsageData();
data.plan = plan;
if (licenseKey) {
data.licenseKey = licenseKey;
}
await this.saveUsageData(data);
}
// Get usage statistics
async getStats() {
const data = await this.loadUsageData();
if (data.events.length === 0) {
return {
totalValidations: 0,
aiDetections: 0,
averageFiles: 0,
averageTime: 0
};
}
const totalValidations = data.events.length;
const aiDetections = data.events.filter(e => e.aiDetected).length;
const totalFiles = data.events.reduce((sum, e) => sum + e.filesCount, 0);
const totalTime = data.events.reduce((sum, e) => sum + e.timeMs, 0);
return {
totalValidations,
aiDetections,
averageFiles: Math.round(totalFiles / totalValidations),
averageTime: Math.round(totalTime / totalValidations)
};
}
// Load usage data from file
async loadUsageData() {
try {
await fs_extra_1.default.ensureDir(path_1.default.dirname(this.usageFile));
if (await fs_extra_1.default.pathExists(this.usageFile)) {
const data = await fs_extra_1.default.readJson(this.usageFile);
return {
plan: 'free',
currentMonth: this.getCurrentMonth(),
validationsThisMonth: 0,
lastReset: new Date().toISOString(),
events: [],
...data
};
}
}
catch (error) {
// If file is corrupted, start fresh
}
// Return default data
return {
plan: 'free',
currentMonth: this.getCurrentMonth(),
validationsThisMonth: 0,
lastReset: new Date().toISOString(),
events: []
};
}
// Save usage data to file
async saveUsageData(data) {
try {
await fs_extra_1.default.ensureDir(path_1.default.dirname(this.usageFile));
await fs_extra_1.default.writeJson(this.usageFile, data, { spaces: 2 });
}
catch (error) {
// Fail silently - usage tracking is not critical
}
}
// Get current month string (YYYY-MM)
getCurrentMonth() {
const now = new Date();
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
}
// Get next reset date (first day of next month)
getNextResetDate() {
const now = new Date();
const nextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1);
return nextMonth.toISOString().split('T')[0];
}
// Clear all usage data (for testing)
async clearUsage() {
try {
if (await fs_extra_1.default.pathExists(this.usageFile)) {
await fs_extra_1.default.remove(this.usageFile);
}
}
catch (error) {
// Fail silently
}
}
}
exports.UsageTracker = UsageTracker;
//# sourceMappingURL=usage-tracker.js.map