@baruchiro/actual-mcp
Version:
Actual Budget MCP server exposing API functionality
63 lines • 2.92 kB
JavaScript
import { getTransactions } from '../../actual-api.js';
import { fetchAllPayees } from './fetch-payees.js';
import { fetchAllCategories } from './fetch-categories.js';
import { GroupAggregator } from '../aggregation/group-by.js';
const groupAggregator = new GroupAggregator();
async function _buildTransactionLookups(options) {
const [payees, categories] = await Promise.all([
options.includePayees ? fetchAllPayees() : Promise.resolve([]),
options.includeCategories ? fetchAllCategories() : Promise.resolve([]),
]);
const payeesById = options.includePayees ? groupAggregator.byId(payees) : {};
const categoriesById = options.includeCategories ? groupAggregator.byId(categories) : {};
return { payeesById, categoriesById };
}
async function _enrichTransactions(transactions) {
if (transactions.length === 0) {
return transactions;
}
// # Reason: Only fetch lookup tables when transactions are missing names to avoid redundant API calls.
const needsPayees = transactions.some((transaction) => Boolean(transaction.payee));
const needsCategories = transactions.some((transaction) => Boolean(transaction.category));
if (!needsPayees && !needsCategories) {
return transactions;
}
const { payeesById, categoriesById } = await _buildTransactionLookups({
includePayees: needsPayees,
includeCategories: needsCategories,
});
return transactions.map((transaction) => {
const payeeName = needsPayees && transaction.payee ? payeesById[transaction.payee]?.name : undefined;
const categoryName = needsCategories && transaction.category ? categoriesById[transaction.category]?.name : undefined;
const enriched = { ...transaction };
if (payeeName !== undefined) {
enriched.payee_name = payeeName;
}
if (categoryName !== undefined) {
enriched.category_name = categoryName;
}
return enriched;
});
}
export async function fetchTransactionsForAccount(accountId, start, end) {
const transactions = await getTransactions(accountId, start, end);
return _enrichTransactions(transactions);
}
export async function fetchAllOnBudgetTransactions(accounts, start, end) {
let transactions = [];
const onBudgetAccounts = accounts.filter((a) => !a.offbudget && !a.closed);
for (const account of onBudgetAccounts) {
const tx = await getTransactions(account.id, start, end);
transactions = [...transactions, ...tx];
}
return _enrichTransactions(transactions);
}
export async function fetchAllTransactions(accounts, start, end) {
let transactions = [];
for (const account of accounts) {
const tx = await getTransactions(account.id, start, end);
transactions = [...transactions, ...tx];
}
return _enrichTransactions(transactions);
}
//# sourceMappingURL=fetch-transactions.js.map