import * as actual from "@actual-app/api" import { ACTUAL_DATA_DIR, ACTUAL_PASSWORD, ACTUAL_SERVER_URL, ACTUAL_SYNC_ID, } from "../config.ts" import type { TransactionEntity } from "@actual-app/api/@types/loot-core/types/models" import { type UUID } from "node:crypto" import logger from "@/logger.ts" export interface Actual { importTransactions: ( accountId: UUID, transactions: Iterable, ) => Promise shutdown: () => Promise } export interface ActualTransaction extends TransactionEntity { account: UUID payee_name?: string } export interface Message { message: string } export interface ImportTransactionsResponse { errors?: Message[] added: number updated: number } export class ActualImpl implements Actual { private constructor() {} static async init(): Promise { await actual.init({ // Budget data will be cached locally here, in subdirectories for each file. dataDir: ACTUAL_DATA_DIR, // This is the URL of your running server serverURL: ACTUAL_SERVER_URL, // This is the password you use to log into the server password: ACTUAL_PASSWORD, }) logger.info(`Initialized ActualBudget API for ${ACTUAL_SERVER_URL}`) await this.downloadBudget() return new ActualImpl() } async importTransactions( accountId: UUID, transactions: Iterable, ): Promise { return actual.importTransactions(accountId, transactions) } async shutdown(): Promise { return actual.shutdown() } private static async downloadBudget(): Promise { await actual.downloadBudget(ACTUAL_SYNC_ID) logger.info(`Downloaded budget`) } }