UNPKG

toggl-jira-sync

Version:

CLI tool to sync Toggl Track time entries to Jira work logs

118 lines (97 loc) 2.8 kB
import { readFileSync, writeFileSync, existsSync } from 'fs'; import { join } from 'path'; import { homedir } from 'os'; const HISTORY_FILE = join(homedir(), '.toggl-jira-history.json'); export class SyncHistory { constructor() { this.historyFile = HISTORY_FILE; this.history = this.load(); } load() { if (!existsSync(this.historyFile)) { return { syncedEntries: {} }; } try { const content = readFileSync(this.historyFile, 'utf8'); return JSON.parse(content); } catch (error) { console.warn('Failed to load sync history, starting fresh:', error.message); return { syncedEntries: {} }; } } save() { try { writeFileSync(this.historyFile, JSON.stringify(this.history, null, 2)); } catch (error) { console.error('Failed to save sync history:', error.message); } } isEntrySynced(togglEntryId) { return !!this.history.syncedEntries[togglEntryId]; } getSyncedEntry(togglEntryId) { return this.history.syncedEntries[togglEntryId]; } markEntriesAsSynced(entries, jiraIssueKey, workLogId) { const syncedAt = new Date().toISOString(); entries.forEach(entry => { this.history.syncedEntries[entry.id] = { togglId: entry.id, description: entry.description, durationSeconds: entry.durationSeconds, startedAt: entry.startedAt, jiraIssueKey, jiraWorkLogId: workLogId, syncedAt }; }); this.save(); } filterUnsyncedEntries(entries) { const synced = []; const unsynced = []; entries.forEach(entry => { if (this.isEntrySynced(entry.id)) { synced.push({ ...entry, syncInfo: this.getSyncedEntry(entry.id) }); } else { unsynced.push(entry); } }); return { synced, unsynced }; } groupSyncedEntriesByIssue(syncedEntries) { const grouped = {}; syncedEntries.forEach(entry => { const issueKey = entry.syncInfo.jiraIssueKey; if (!grouped[issueKey]) { grouped[issueKey] = { issueKey, entries: [], totalSeconds: 0 }; } grouped[issueKey].entries.push(entry); grouped[issueKey].totalSeconds += entry.durationSeconds; }); return grouped; } clear() { this.history = { syncedEntries: {} }; this.save(); } getStats() { const entries = Object.values(this.history.syncedEntries); const totalEntries = entries.length; const totalSeconds = entries.reduce((sum, entry) => sum + entry.durationSeconds, 0); const issueKeys = [...new Set(entries.map(e => e.jiraIssueKey))]; return { totalEntries, totalSeconds, uniqueIssues: issueKeys.length, issues: issueKeys }; } }