UNPKG

@vpdn/moneymoney-cli

Version:

Command-line interface for MoneyMoney app - list accounts and fetch transactions

188 lines 7.31 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.MoneyMoneyAppleScript = void 0; const child_process_1 = require("child_process"); const util_1 = require("util"); const plist = __importStar(require("plist")); const execAsync = (0, util_1.promisify)(child_process_1.exec); class MoneyMoneyAppleScript { /** * Execute an AppleScript command */ async runAppleScript(script) { try { const { stdout, stderr } = await execAsync(`osascript -e '${script}'`); if (stderr) { throw new Error(`AppleScript error: ${stderr}`); } return stdout.trim(); } catch (error) { throw new Error(`Failed to execute AppleScript: ${error}`); } } /** * Get all accounts from MoneyMoney */ async getAccounts() { const script = 'tell application "MoneyMoney" to export accounts'; const result = await this.runAppleScript(script); try { const parsed = plist.parse(result); if (!parsed || !Array.isArray(parsed)) { throw new Error('Invalid accounts data format'); } return parsed.map((acc) => ({ accountNumber: acc.accountNumber || '', name: acc.name || '', owner: acc.owner, bankCode: acc.bankCode, currency: acc.currency || this.parseCurrency(acc.balance), balance: this.parseBalance(acc.balance), type: acc.type })); } catch (error) { throw new Error(`Failed to parse accounts data: ${error}`); } } /** * Export transactions for specific accounts and date range */ async getTransactions(options) { const format = options.format || 'plist'; // MoneyMoney requires both from and to dates when exporting transactions // If not provided, use sensible defaults const fromDate = options.fromDate || new Date(new Date().getFullYear(), 0, 1); // Start of current year const toDate = options.toDate || new Date(); // Today const fromDateStr = this.formatDate(fromDate); const toDateStr = this.formatDate(toDate); let script = `tell application "MoneyMoney" to export transactions from date "${fromDateStr}" to date "${toDateStr}"`; // Add account filter if provided if (options.accountNumbers && options.accountNumbers.length > 0) { // Try with 'from account' for single account script = `tell application "MoneyMoney" to export transactions from account "${options.accountNumbers[0]}" from date "${fromDateStr}" to date "${toDateStr}"`; } script += ` as "${format}"`; const result = await this.runAppleScript(script); if (format === 'csv') { return result; } // Parse plist format try { const parsed = plist.parse(result); // Check if it's wrapped in a dictionary with transactions key let transactions; if (parsed && parsed.transactions && Array.isArray(parsed.transactions)) { transactions = parsed.transactions; } else if (Array.isArray(parsed)) { transactions = parsed; } else { throw new Error('Invalid transactions data format'); } return transactions.map((trans) => ({ name: trans.name || '', accountNumber: trans.accountNumber, amount: trans.amount || 0, bookingDate: trans.bookingDate ? new Date(trans.bookingDate) : new Date(), valueDate: trans.valueDate ? new Date(trans.valueDate) : undefined, purpose: trans.purpose, category: trans.category, comment: trans.comment })); } catch (error) { throw new Error(`Failed to parse transactions data: ${error}`); } } /** * Export transactions for multiple accounts */ async getTransactionsMultipleAccounts(options) { const allTransactions = []; for (const accountNumber of options.accountNumbers) { const transactions = await this.getTransactions({ accountNumbers: [accountNumber], fromDate: options.fromDate, toDate: options.toDate, format: 'plist' }); allTransactions.push(...transactions); } return allTransactions; } /** * Parse balance from MoneyMoney format */ parseBalance(balance) { if (!balance || !Array.isArray(balance) || balance.length === 0) { return undefined; } // Balance format is [[amount, currency]] const firstBalance = balance[0]; if (Array.isArray(firstBalance) && firstBalance.length >= 1) { return firstBalance[0]; } return undefined; } /** * Parse currency from MoneyMoney balance format */ parseCurrency(balance) { if (!balance || !Array.isArray(balance) || balance.length === 0) { return undefined; } // Balance format is [[amount, currency]] const firstBalance = balance[0]; if (Array.isArray(firstBalance) && firstBalance.length >= 2) { return firstBalance[1]; } return undefined; } /** * Format date for AppleScript */ formatDate(date) { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } } exports.MoneyMoneyAppleScript = MoneyMoneyAppleScript; //# sourceMappingURL=applescript.js.map