UNPKG

jrnl-mcp

Version:

Model Context Protocol server for jrnl CLI journal application

104 lines (103 loc) 4.12 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getStatistics = getStatistics; const commandBuilder_1 = require("../utils/commandBuilder"); const dateUtils_1 = require("../utils/dateUtils"); async function getStatistics(journal, timeGrouping, includeTopTags, executor) { const command = (0, commandBuilder_1.buildStatsCommand)(journal); const result = await executor.execute(command); try { const data = JSON.parse(result); const entries = data.entries || []; // Calculate basic statistics const totalEntries = entries.length; const totalWords = entries.reduce((sum, entry) => { const bodyWords = entry.body ? entry.body.split(/\s+/).length : 0; const titleWords = entry.title ? entry.title.split(/\s+/).length : 0; return sum + bodyWords + titleWords; }, 0); const averageWordsPerEntry = totalEntries > 0 ? Math.round(totalWords / totalEntries) : 0; const statistics = { totalEntries, totalWords, averageWordsPerEntry, }; // Time grouping statistics if (timeGrouping) { const grouping = (0, dateUtils_1.parseTimeGrouping)(timeGrouping); const grouped = groupEntriesByTime(entries, grouping); statistics.timeGrouping = Object.entries(grouped).map(([period, entries]) => { const wordCount = entries.reduce((sum, entry) => { const bodyWords = entry.body ? entry.body.split(/\s+/).length : 0; const titleWords = entry.title ? entry.title.split(/\s+/).length : 0; return sum + bodyWords + titleWords; }, 0); return { period, entryCount: entries.length, wordCount, }; }); } // Top tags if (includeTopTags) { const tagCounts = new Map(); entries.forEach((entry) => { if (entry.tags) { entry.tags.forEach((tag) => { const normalizedTag = tag.startsWith("@") ? tag : `@${tag}`; tagCounts.set(normalizedTag, (tagCounts.get(normalizedTag) || 0) + 1); }); } }); statistics.topTags = Array.from(tagCounts.entries()) .map(([tag, count]) => ({ tag, count })) .sort((a, b) => b.count - a.count) .slice(0, 10); // Top 10 tags } return { statistics }; } catch (error) { throw new Error(`Failed to calculate statistics: ${error}`); } } function groupEntriesByTime(entries, grouping) { const grouped = {}; entries.forEach((entry) => { const date = new Date(entry.date); let key; switch (grouping) { case "daily": key = date.toISOString().split("T")[0]; break; case "weekly": { // Get week number const weekNum = getWeekNumber(date); key = `${date.getFullYear()}-W${weekNum}`; break; } case "monthly": key = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}`; break; case "yearly": key = date.getFullYear().toString(); break; default: key = date.toISOString().split("T")[0]; } if (!grouped[key]) { grouped[key] = []; } grouped[key].push(entry); }); return grouped; } function getWeekNumber(date) { const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())); const dayNum = d.getUTCDay() || 7; d.setUTCDate(d.getUTCDate() + 4 - dayNum); const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1)); return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7); }