mirror of
https://github.com/heroblackink/ultimate-todoist-sync-for-obsidian.git
synced 2026-07-22 07:40:27 +00:00
refactor: redesign logging system with single file + size-based cleanup
- Change LogAction to string type for flexibility - Rename todayLogs to memoryLogs - Use single log file (todoist-sync-logs.json) - Add size-based cleanup (maxLogFileSize, logRetentionPercent) - Remove batch buffer, use memoryLogs directly - Update settings with new log config options - Remove legacy logs array and logRetentionDays
This commit is contained in:
parent
1450a120b3
commit
c209a6d1ea
4 changed files with 126 additions and 332 deletions
8
main.ts
8
main.ts
|
|
@ -302,9 +302,9 @@ export default class UltimateTodoistSyncForObsidian extends Plugin {
|
|||
|
||||
// Flush log buffer before unloading
|
||||
try {
|
||||
await this.logOperation?.flushLogBuffer();
|
||||
await this.logOperation?.flushToFile();
|
||||
} catch (error) {
|
||||
console.error('An error occurred in flushLogBuffer:', error);
|
||||
console.error('An error occurred in flushToFile:', error);
|
||||
}
|
||||
|
||||
await this.saveSettings()
|
||||
|
|
@ -838,9 +838,9 @@ export default class UltimateTodoistSyncForObsidian extends Plugin {
|
|||
|
||||
// Flush log buffer after sync completes
|
||||
try {
|
||||
await this.logOperation?.flushLogBuffer();
|
||||
await this.logOperation?.flushToFile();
|
||||
} catch (error) {
|
||||
console.error('An error occurred in flushLogBuffer:', error);
|
||||
console.error('An error occurred in flushToFile:', error);
|
||||
}
|
||||
|
||||
console.log("Todoist scheduled synchronization task completed at", new Date().toLocaleString());
|
||||
|
|
|
|||
|
|
@ -3,158 +3,32 @@ import UltimateTodoistSyncForObsidian from "../main";
|
|||
|
||||
export interface LogEntry {
|
||||
timestamp: number;
|
||||
action: LogAction;
|
||||
action: string;
|
||||
details: string;
|
||||
filePath?: string;
|
||||
taskId?: string;
|
||||
}
|
||||
|
||||
export type LogAction =
|
||||
// Task operations - User actions in Obsidian
|
||||
| 'OBSIDIAN_TASK_CREATED'
|
||||
| 'OBSIDIAN_TASK_MODIFIED'
|
||||
| 'OBSIDIAN_TASK_DELETED'
|
||||
| 'OBSIDIAN_TASK_COMPLETED'
|
||||
| 'OBSIDIAN_TASK_REOPENED'
|
||||
| 'OBSIDIAN_TASK_CONTENT_CHANGED'
|
||||
| 'OBSIDIAN_TASK_DUEDATE_CHANGED'
|
||||
| 'OBSIDIAN_TASK_PRIORITY_CHANGED'
|
||||
| 'OBSIDIAN_TASK_LABEL_CHANGED'
|
||||
// File operations
|
||||
| 'FILE_MODIFIED'
|
||||
| 'FILE_RENAMED'
|
||||
| 'FILE_TODOIST_TAG_ADDED'
|
||||
| 'FILE_TASK_COMPLETED'
|
||||
| 'FILE_TASK_UNCOMPLETED'
|
||||
| 'FILE_TASK_CONTENT_SYNCED'
|
||||
| 'FILE_TASK_DUEDATE_SYNCED'
|
||||
| 'FILE_TASK_NOTE_ADDED'
|
||||
// Cache operations
|
||||
| 'CACHE_TASK_ADDED'
|
||||
| 'CACHE_TASK_UPDATED'
|
||||
| 'CACHE_TASK_DELETED'
|
||||
| 'CACHE_TASK_NONACTIVE'
|
||||
| 'CACHE_TASK_CONFLICTED'
|
||||
| 'CACHE_TASK_ISSUE'
|
||||
| 'CACHE_TASK_NON_ID'
|
||||
| 'CACHE_TASK_COMPLETED'
|
||||
| 'CACHE_TASK_REOPENED'
|
||||
| 'CACHE_FILE_METADATA_UPDATED'
|
||||
| 'CACHE_FILE_METADATA_DELETED'
|
||||
| 'CACHE_RENAMED'
|
||||
| 'CACHE_REBUILT'
|
||||
| 'DATABASE_CHECK'
|
||||
| 'DATABASE_CHECKED'
|
||||
// Todoist API operations
|
||||
| 'TODOIST_TASK_CREATED'
|
||||
| 'TODOIST_TASK_UPDATED'
|
||||
| 'TODOIST_TASK_DELETED'
|
||||
| 'TODOIST_TASK_COMPLETED'
|
||||
| 'TODOIST_TASK_REOPENED'
|
||||
// Sync operations
|
||||
| 'SYNC_START'
|
||||
| 'SYNC_COMPLETED'
|
||||
| 'SYNC_ERROR'
|
||||
| 'BACKUP_CREATED'
|
||||
| 'PROJECT_UPDATED'
|
||||
| 'PLUGIN_INITIALIZED'
|
||||
| 'SETTINGS_UPDATED';
|
||||
export type LogAction = string;
|
||||
|
||||
export class LogOperation {
|
||||
app: App;
|
||||
plugin: UltimateTodoistSyncForObsidian;
|
||||
private maxLogs = 500;
|
||||
private currentDate = '';
|
||||
private todayLogs: LogEntry[] = [];
|
||||
private lastCleanupDate = '';
|
||||
private logBuffer: LogEntry[] = [];
|
||||
private app: App;
|
||||
private plugin: UltimateTodoistSyncForObsidian;
|
||||
private memoryLogs: LogEntry[] = [];
|
||||
private unsavedCount = 0;
|
||||
private readonly BATCH_SIZE = 20;
|
||||
|
||||
constructor(app: App, plugin: UltimateTodoistSyncForObsidian) {
|
||||
this.app = app;
|
||||
this.plugin = plugin;
|
||||
this.initializeLogs();
|
||||
this.loadTodayLogsFromFile();
|
||||
this.loadLogsFromFile();
|
||||
}
|
||||
|
||||
private initializeLogs(): void {
|
||||
const today = this.getTodayDateString();
|
||||
this.currentDate = today;
|
||||
this.lastCleanupDate = today;
|
||||
|
||||
if (this.plugin.settings.logFileEnabled) {
|
||||
this.migrateLegacyLogs();
|
||||
}
|
||||
|
||||
this.todayLogs = [];
|
||||
|
||||
if (this.plugin.settings.debugMode) {
|
||||
console.log(`[LogOperation] Initialized`);
|
||||
}
|
||||
}
|
||||
|
||||
private async loadTodayLogsFromFile(): Promise<void> {
|
||||
if (!this.plugin.storagePathManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const logPath = await this.plugin.storagePathManager.getTodayLogPath();
|
||||
const adapter = this.plugin.app.vault.adapter;
|
||||
|
||||
const exists = await adapter.exists(logPath);
|
||||
if (exists) {
|
||||
const content = await adapter.read(logPath);
|
||||
try {
|
||||
const data = JSON.parse(content);
|
||||
if (Array.isArray(data)) {
|
||||
this.todayLogs = data;
|
||||
if (this.plugin.settings.debugMode) {
|
||||
console.log(`[LogOperation] Loaded ${data.length} logs from today's file`);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
this.todayLogs = [];
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[LogOperation] Failed to load today logs from file:', error);
|
||||
this.todayLogs = [];
|
||||
}
|
||||
}
|
||||
|
||||
private getTodayDateString(): string {
|
||||
const now = new Date();
|
||||
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
private migrateLegacyLogs(): void {
|
||||
const legacyLogs = this.plugin.settings.logs;
|
||||
if (legacyLogs && legacyLogs.length > 0) {
|
||||
if (this.plugin.settings.debugMode) {
|
||||
console.log(`[LogOperation] Migrating ${legacyLogs.length} legacy logs to file`);
|
||||
}
|
||||
|
||||
for (const entry of legacyLogs) {
|
||||
this.appendToLogFile(entry);
|
||||
}
|
||||
|
||||
this.plugin.settings.logs = [];
|
||||
this.plugin.saveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
log(action: LogAction, details: string, filePath?: string, taskId?: string): void {
|
||||
log(action: string, details: string, filePath?: string, taskId?: string): void {
|
||||
if (!this.plugin.settings.enableLog) {
|
||||
return;
|
||||
}
|
||||
|
||||
const today = this.getTodayDateString();
|
||||
|
||||
if (today !== this.currentDate) {
|
||||
this.handleDateChange(today);
|
||||
}
|
||||
|
||||
const logEntry: LogEntry = {
|
||||
timestamp: Date.now(),
|
||||
action,
|
||||
|
|
@ -163,190 +37,154 @@ export class LogOperation {
|
|||
taskId
|
||||
};
|
||||
|
||||
this.todayLogs.push(logEntry);
|
||||
|
||||
if (this.todayLogs.length > this.maxLogs) {
|
||||
this.todayLogs.shift();
|
||||
}
|
||||
this.memoryLogs.push(logEntry);
|
||||
|
||||
if (this.plugin.settings.logFileEnabled) {
|
||||
this.logBuffer.push(logEntry);
|
||||
if (this.logBuffer.length >= this.BATCH_SIZE) {
|
||||
this.flushLogBuffer();
|
||||
this.unsavedCount++;
|
||||
if (this.unsavedCount >= this.BATCH_SIZE) {
|
||||
this.flushToFile();
|
||||
}
|
||||
}
|
||||
|
||||
this.cleanOldLogsIfNeeded();
|
||||
|
||||
if (this.plugin.settings.debugMode) {
|
||||
console.log(`[Log] ${action}: ${details}`, { filePath, taskId });
|
||||
}
|
||||
}
|
||||
|
||||
private handleDateChange(newDate: string): void {
|
||||
this.todayLogs = [];
|
||||
this.currentDate = newDate;
|
||||
|
||||
if (this.plugin.settings.debugMode) {
|
||||
console.log(`[LogOperation] Date changed to ${newDate}, buffer cleared`);
|
||||
}
|
||||
}
|
||||
|
||||
private async appendToLogFile(entry: LogEntry): Promise<void> {
|
||||
if (!this.plugin.storagePathManager) {
|
||||
console.warn('[LogOperation] StoragePathManager not initialized');
|
||||
private async loadLogsFromFileAsync(): Promise<void> {
|
||||
if (!this.plugin.settings.logFileEnabled || !this.plugin.storagePathManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.plugin.storagePathManager.ensureAllDirs();
|
||||
const logPath = await this.plugin.storagePathManager.getTodayLogPath();
|
||||
await this.plugin.storagePathManager.appendJsonToFile(logPath, entry);
|
||||
} catch (error) {
|
||||
console.error('[LogOperation] Failed to append log to file:', error);
|
||||
}
|
||||
}
|
||||
|
||||
public async flushLogBuffer(): Promise<void> {
|
||||
if (this.logBuffer.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.plugin.storagePathManager) {
|
||||
console.warn('[LogOperation] StoragePathManager not initialized');
|
||||
this.logBuffer = [];
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.plugin.storagePathManager.ensureAllDirs();
|
||||
const logPath = await this.plugin.storagePathManager.getTodayLogPath();
|
||||
|
||||
const adapter = this.plugin.app.vault.adapter;
|
||||
let data: LogEntry[] = [];
|
||||
const logPath = this.plugin.storagePathManager.getLogFilePath();
|
||||
const adapter = this.app.vault.adapter;
|
||||
|
||||
const exists = await adapter.exists(logPath);
|
||||
if (exists) {
|
||||
const content = await adapter.read(logPath);
|
||||
try {
|
||||
data = JSON.parse(content);
|
||||
if (!Array.isArray(data)) {
|
||||
data = [];
|
||||
if (content) {
|
||||
try {
|
||||
const data = JSON.parse(content);
|
||||
if (Array.isArray(data)) {
|
||||
this.memoryLogs = data;
|
||||
if (this.plugin.settings.debugMode) {
|
||||
console.log(`[LogOperation] Loaded ${data.length} logs from file`);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
this.memoryLogs = [];
|
||||
}
|
||||
} catch {
|
||||
data = [];
|
||||
}
|
||||
}
|
||||
|
||||
data.push(...this.logBuffer);
|
||||
await adapter.write(logPath, JSON.stringify(data, null, 2));
|
||||
this.logBuffer = [];
|
||||
|
||||
if (this.plugin.settings.debugMode) {
|
||||
console.log(`[LogOperation] Flushed ${this.logBuffer.length} logs to file`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[LogOperation] Failed to flush log buffer:', error);
|
||||
console.error('[LogOperation] Failed to load logs from file:', error);
|
||||
this.memoryLogs = [];
|
||||
}
|
||||
}
|
||||
|
||||
private cleanOldLogsIfNeeded(): void {
|
||||
const today = this.getTodayDateString();
|
||||
|
||||
if (today === this.lastCleanupDate) {
|
||||
private loadLogsFromFile(): void {
|
||||
this.loadLogsFromFileAsync();
|
||||
}
|
||||
|
||||
public async flushToFile(): Promise<void> {
|
||||
if (!this.plugin.settings.logFileEnabled || !this.plugin.storagePathManager) {
|
||||
this.unsavedCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastCleanupDate = today;
|
||||
|
||||
if (this.plugin.settings.logFileEnabled && this.plugin.storagePathManager) {
|
||||
this.cleanOldLogs().catch(error => {
|
||||
console.error('[LogOperation] Failed to clean old logs:', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async cleanOldLogs(): Promise<void> {
|
||||
const retentionDays = this.plugin.settings.logRetentionDays || 365;
|
||||
const cutoffDate = new Date();
|
||||
cutoffDate.setDate(cutoffDate.getDate() - retentionDays);
|
||||
const cutoffString = `${cutoffDate.getFullYear()}-${String(cutoffDate.getMonth() + 1).padStart(2, '0')}-${String(cutoffDate.getDate()).padStart(2, '0')}`;
|
||||
|
||||
try {
|
||||
const logsPath = await this.plugin.storagePathManager.getLogsPath();
|
||||
const files = await this.plugin.storagePathManager.listFiles(logsPath);
|
||||
await this.plugin.storagePathManager.ensureDir(
|
||||
this.plugin.storagePathManager.getLogsBasePath()
|
||||
);
|
||||
|
||||
for (const filePath of files) {
|
||||
const fileName = filePath.split('/').pop() || '';
|
||||
const dateMatch = fileName.match(/_(\d{4}-\d{2}-\d{2})\.json$/);
|
||||
|
||||
if (dateMatch) {
|
||||
const fileDate = dateMatch[1];
|
||||
if (fileDate < cutoffString) {
|
||||
await this.plugin.storagePathManager.deleteFile(filePath);
|
||||
|
||||
if (this.plugin.settings.debugMode) {
|
||||
console.log(`[LogOperation] Deleted old log file: ${filePath}`);
|
||||
const logPath = this.plugin.storagePathManager.getLogFilePath();
|
||||
const adapter = this.app.vault.adapter;
|
||||
|
||||
let currentLogs: LogEntry[] = [];
|
||||
const exists = await adapter.exists(logPath);
|
||||
if (exists) {
|
||||
const content = await adapter.read(logPath);
|
||||
if (content) {
|
||||
try {
|
||||
currentLogs = JSON.parse(content);
|
||||
if (!Array.isArray(currentLogs)) {
|
||||
currentLogs = [];
|
||||
}
|
||||
} catch {
|
||||
currentLogs = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const maxSize = this.plugin.settings.maxLogFileSize || (1024 * 1024);
|
||||
const content = JSON.stringify(currentLogs, null, 2);
|
||||
const currentSize = content.length;
|
||||
|
||||
if (currentSize > maxSize) {
|
||||
await this.cleanupBySize();
|
||||
} else {
|
||||
currentLogs.push(...this.memoryLogs);
|
||||
await adapter.write(logPath, JSON.stringify(currentLogs, null, 2));
|
||||
}
|
||||
|
||||
this.memoryLogs = [];
|
||||
this.unsavedCount = 0;
|
||||
|
||||
if (this.plugin.settings.debugMode) {
|
||||
console.log(`[LogOperation] Flushed logs to file`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[LogOperation] Error cleaning old logs:', error);
|
||||
console.error('[LogOperation] Failed to flush logs to file:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private async cleanupBySize(): Promise<void> {
|
||||
try {
|
||||
const logPath = this.plugin.storagePathManager!.getLogFilePath();
|
||||
const adapter = this.app.vault.adapter;
|
||||
|
||||
let currentLogs: LogEntry[] = [];
|
||||
const exists = await adapter.exists(logPath);
|
||||
if (exists) {
|
||||
const content = await adapter.read(logPath);
|
||||
if (content) {
|
||||
try {
|
||||
currentLogs = JSON.parse(content);
|
||||
if (!Array.isArray(currentLogs)) {
|
||||
currentLogs = [];
|
||||
}
|
||||
} catch {
|
||||
currentLogs = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const retentionPercent = this.plugin.settings.logRetentionPercent || 80;
|
||||
const keepCount = Math.floor(currentLogs.length * retentionPercent / 100);
|
||||
const trimmedLogs = currentLogs.slice(-keepCount);
|
||||
|
||||
trimmedLogs.push(...this.memoryLogs);
|
||||
await adapter.write(logPath, JSON.stringify(trimmedLogs, null, 2));
|
||||
|
||||
this.memoryLogs = trimmedLogs.slice(-this.BATCH_SIZE);
|
||||
|
||||
if (this.plugin.settings.debugMode) {
|
||||
console.log(`[LogOperation] Cleaned up logs, kept ${keepCount} entries`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[LogOperation] Failed to cleanup logs:', error);
|
||||
}
|
||||
}
|
||||
|
||||
getLogs(): LogEntry[] {
|
||||
return this.todayLogs;
|
||||
}
|
||||
|
||||
getAllLogs(): LogEntry[] {
|
||||
if (!this.plugin.settings.logFileEnabled || !this.plugin.storagePathManager) {
|
||||
return this.todayLogs;
|
||||
}
|
||||
|
||||
return this.todayLogs;
|
||||
}
|
||||
|
||||
async getLogsFromFiles(days = 30): Promise<LogEntry[]> {
|
||||
if (!this.plugin.settings.logFileEnabled || !this.plugin.storagePathManager) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const logs: LogEntry[] = [];
|
||||
|
||||
try {
|
||||
const logsPath = await this.plugin.storagePathManager.getLogsPath();
|
||||
const files = await this.plugin.storagePathManager.listFiles(logsPath);
|
||||
|
||||
const cutoffDate = new Date();
|
||||
cutoffDate.setDate(cutoffDate.getDate() - days);
|
||||
|
||||
for (const filePath of files) {
|
||||
const fileName = filePath.split('/').pop() || '';
|
||||
const dateMatch = fileName.match(/_(\d{4}-\d{2}-\d{2})\.json$/);
|
||||
|
||||
if (dateMatch) {
|
||||
const fileDate = new Date(dateMatch[1]);
|
||||
if (fileDate >= cutoffDate) {
|
||||
const data = await this.plugin.storagePathManager.readJsonFile<LogEntry[]>(filePath);
|
||||
if (data && Array.isArray(data)) {
|
||||
logs.push(...data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[LogOperation] Failed to read logs from files:', error);
|
||||
}
|
||||
|
||||
return logs;
|
||||
return this.memoryLogs;
|
||||
}
|
||||
|
||||
getLogsAsText(): string {
|
||||
const logs = this.getLogs();
|
||||
if (logs.length === 0) {
|
||||
return 'No logs available. (Today\'s logs will appear here)';
|
||||
return 'No logs available.';
|
||||
}
|
||||
|
||||
return logs.map(log => {
|
||||
|
|
@ -357,49 +195,8 @@ export class LogOperation {
|
|||
}).join('\n');
|
||||
}
|
||||
|
||||
async getLogsAsTextFromFiles(days = 7): Promise<string> {
|
||||
const logs = await this.getLogsFromFiles(days);
|
||||
|
||||
if (logs.length === 0) {
|
||||
return 'No logs available in files.';
|
||||
}
|
||||
|
||||
logs.sort((a, b) => a.timestamp - b.timestamp);
|
||||
|
||||
return logs.map(log => {
|
||||
const date = new Date(log.timestamp).toLocaleString();
|
||||
const fileInfo = log.filePath ? ` [${log.filePath}]` : '';
|
||||
const taskInfo = log.taskId ? ` (task: ${log.taskId})` : '';
|
||||
return `[${date}] ${log.action}: ${log.details}${fileInfo}${taskInfo}`;
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
clearLogs(): void {
|
||||
this.todayLogs = [];
|
||||
this.flushLogBuffer();
|
||||
}
|
||||
|
||||
async exportLogsToFile(): Promise<string | null> {
|
||||
const logsText = await this.getLogsAsTextFromFiles(365);
|
||||
|
||||
try {
|
||||
const logsPath = await this.plugin.storagePathManager.getLogsPath();
|
||||
await this.plugin.storagePathManager.ensureDir(logsPath);
|
||||
|
||||
const exportFileName = `logs-export-${this.getTodayDateString()}.md`;
|
||||
const exportPath = `${logsPath}/${exportFileName}`;
|
||||
|
||||
const adapter = this.app.vault.adapter;
|
||||
await adapter.write(exportPath, logsText);
|
||||
|
||||
return exportPath;
|
||||
} catch (error) {
|
||||
console.error('[LogOperation] Failed to export logs:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
exportLogs(): string {
|
||||
return this.getLogsAsText();
|
||||
this.memoryLogs = [];
|
||||
this.flushToFile();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { App, Notice, PluginSettingTab, Setting } from 'obsidian';
|
||||
import UltimateTodoistSyncForObsidian from "../main";
|
||||
import { LogAction } from './logOperation';
|
||||
|
||||
export interface UltimateTodoistSyncSettings {
|
||||
initialized: boolean;
|
||||
|
|
@ -30,15 +29,9 @@ export interface UltimateTodoistSyncSettings {
|
|||
syncDataCache: Record<string, any> | null;
|
||||
deviceIdGenerated: boolean;
|
||||
enableLog: boolean;
|
||||
logs: Array<{
|
||||
timestamp: number;
|
||||
action: LogAction;
|
||||
details: string;
|
||||
filePath?: string;
|
||||
taskId?: string;
|
||||
}>;
|
||||
logFileEnabled: boolean;
|
||||
logRetentionDays: number;
|
||||
maxLogFileSize: number;
|
||||
logRetentionPercent: number;
|
||||
maxBackupsPerFile: number;
|
||||
storageDirectory: string;
|
||||
lastStorageDirectory: string | null;
|
||||
|
|
@ -65,9 +58,9 @@ export const DEFAULT_SETTINGS: UltimateTodoistSyncSettings = {
|
|||
syncDataCache: null,
|
||||
deviceIdGenerated: false,
|
||||
enableLog: true,
|
||||
logs: [],
|
||||
logFileEnabled: true,
|
||||
logRetentionDays: 365,
|
||||
maxLogFileSize: 1024 * 1024,
|
||||
logRetentionPercent: 80,
|
||||
maxBackupsPerFile: 100,
|
||||
storageDirectory: 'ultimate-todoist-sync',
|
||||
lastStorageDirectory: null,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@ export class StoragePathManager {
|
|||
return `${this.getBasePath()}/logs`;
|
||||
}
|
||||
|
||||
getLogFilePath(): string {
|
||||
return `${this.getLogsBasePath()}/todoist-sync-logs.json`;
|
||||
}
|
||||
|
||||
getBackupsBasePath(): string {
|
||||
return `${this.getBasePath()}/backups`;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue