@vpdn/moneymoney-cli
Version:
Command-line interface for MoneyMoney app - list accounts and fetch transactions
188 lines • 7.31 kB
JavaScript
;
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