jrnl-mcp
Version:
Model Context Protocol server for jrnl CLI journal application
104 lines (103 loc) • 4.12 kB
JavaScript
;
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);
}