import { ACTUAL_BUDGET_ID, ACTUAL_HOST, ACTUAL_PASS } from "$env/static/private"; import * as actual from "@actual-app/api" import { existsSync, mkdirSync } from "node:fs"; import path from "node:path" import process from "node:process"; import type { Sb1Transaction } from "./sb1"; import type { ImportTransactionEntity } from "@actual-app/api/@types/loot-core/src/types/models/import-transaction"; import { Temporal } from "temporal-polyfill"; async function init_actual() { const dataDir = path.resolve(process.cwd(), "data/actualDataDir") if (!existsSync(dataDir)) mkdirSync(dataDir, { recursive: true }); return actual.init({ password: ACTUAL_PASS, serverURL: ACTUAL_HOST, dataDir: dataDir }).then(async () => { await actual.downloadBudget(ACTUAL_BUDGET_ID) await actual.sync() }) } export async function import_transactions(account: string, transactions: Sb1Transaction[], dryRun: boolean) { function parsedDate(date: number) { const instant = Temporal.Instant.fromEpochMilliseconds(date) return instant.toString({ timeZone: "Europe/Oslo" }).split("T")[0] } const actualMappedTransactions: ImportTransactionEntity[] = transactions.filter(c => c.bookingStatus === "BOOKED").map(c => ({ account, date: parsedDate(c.date), amount: c.amount, notes: c.description, payee_name: c.cleanedDescription })) actual.importTransactions(account, actualMappedTransactions, { dryRun }) } export async function get_budgets() { await init_actual() return actual.getBudgets() } export async function get_accounts() { await init_actual() return actual.getAccounts() }