split-expense-ynab-venmo-shared
Version:
Shared library code the app Expo+Firebase app 'Split Expense: YNAB + Venmo'
80 lines (67 loc) • 2.42 kB
text/typescript
import { objectKeys } from 'ts-extras';
import { Account, API, SaveTransaction } from 'ynab';
import { z } from 'zod';
type YNABConfig = z.infer<typeof YNABEnvVarsSchema>;
export class YNABClient {
#config: YNABConfig;
#ynabApi: API;
constructor(config: YNABConfig) {
this.#config = config;
this.#ynabApi = new API(this.#config.YNAB_API_TOKEN);
}
async getDefaultBudget() {
const budgetsResponse = await this.#ynabApi.budgets.getBudgets();
const firstBudget = budgetsResponse.data.budgets[0];
if (!firstBudget) throw new Error('No budget found.');
return firstBudget;
}
async getAccounts(): Promise<Account[]> {
const response = await this.#ynabApi.accounts.getAccounts(this.#config.DEFAULT_BUDGET_ID);
return response.data.accounts;
}
async getCategoryGroups() {
const budget = await this.getDefaultBudget();
const categoriesResponse = await this.#ynabApi.categories.getCategories(budget.id);
return categoriesResponse.data.category_groups;
}
async getCategoriesFlat() {
const categoryGroups = await this.getCategoryGroups();
const categoriesFlat = categoryGroups
.filter((group) => !group.hidden)
.map((group) => group.categories)
.flat();
return categoriesFlat;
}
async addTransactions(transactions: TransactionDetails[]) {
try {
await this.#ynabApi.transactions.createTransaction(this.#config.DEFAULT_BUDGET_ID, {
transactions: transactions.map((transaction) => this.createTransaction(transaction)),
});
} catch (e) {
console.error(e);
}
}
createTransaction(transactionDetails: TransactionDetails): SaveTransaction {
return {
account_id: transactionDetails.accountId,
amount: transactionDetails.cents * 10,
date: new Date().toISOString().split('T')[0],
payee_name: transactionDetails.payeeName,
memo: transactionDetails.memo,
category_id: transactionDetails.categoryId,
};
}
}
export const YNABEnvVarsSchema = z.object({
YNAB_API_TOKEN: z.string(),
DEFAULT_BUDGET_ID: z.string(),
});
export const YNAB_ENV_VARS = objectKeys(YNABEnvVarsSchema.keyof().Values);
export const TransactionDetailsSchema = z.object({
accountId: z.string(),
cents: z.number(),
payeeName: z.string(),
memo: z.string().optional(),
categoryId: z.string(),
});
export type TransactionDetails = z.infer<typeof TransactionDetailsSchema>;