UNPKG

ynab-api-importer

Version:

Import bank transactions into YNAB

114 lines 12.1 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 (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.bnzAdapter = void 0; const F = __importStar(require("fp-ts/function")); const O = __importStar(require("fp-ts/Option")); const luxon_1 = require("luxon"); const __1 = require("../../"); const login = (page) => async (accessNumber, password, retries = 0) => { await page.setBypassCSP(true); await page.goto("https://secure.bnz.co.nz/auth/personal-login"); await page.type("input#field-principal", accessNumber); await page.type("input#field-credentials", password); await page.click("button[type=submit]"); try { const el = await Promise.race([ page.waitForSelector("span.js-main-menu-button-text"), page.waitForSelector("input[title=Accept]"), ]); if (el) { await el.click(); } await page.waitForSelector("span.js-main-menu-button-text"); } catch (e) { if (retries > 3) { throw e; } await login(page)(accessNumber, password, retries + 1); } }; const request = (page) => (path, opts = {}) => page.evaluate((path, opts) => fetch(`https://www.bnz.co.nz/ib/api${path}`, { credentials: "same-origin", ...opts, }).then(r => r.json()), path, opts); const getAccounts = (page) => request(page)("/accounts"); const findAccount = (list) => (accountName) => O.fromNullable(list.accountList.find(a => a.nickname === accountName)); const listTransactions = (page) => (accountID) => { const nzTime = luxon_1.DateTime.utc().setZone("Pacific/Auckland"); const fromDate = nzTime.minus({ days: 8 }).toISODate(); const toDate = nzTime.plus({ days: 1 }).toISODate(); return request(page)(`/transactions?from=${fromDate}&to=${toDate}&account=${accountID}`); }; const isPending = (t) => t.status.code !== "POSTED"; const isInternational = (t) => t.value.currency !== "NZD"; const isPendingInternational = (t) => isPending(t) && isInternational(t); const filterPendingInternational = (t) => t.filter(t => !isPendingInternational(t)); const filterPending = (t) => t.filter(t => !isPending(t)); const dateTime = (timestamp) => luxon_1.DateTime.fromISO(timestamp, { zone: "Pacific/Auckland" }); const isFuture = (t) => dateTime(t.timestamp) > luxon_1.DateTime.local(); const filterFuture = (transactions) => transactions.filter(t => !isFuture(t)); const memoFromTransaction = ({ thisAccount: { details }, }) => [details.particulars, details.reference, details.code] .filter(s => !!s) .join(" "); const payeeFromTransaction = (t) => F.pipe(O.fromNullable(t.otherAccount.holder.name), O.alt(() => O.fromNullable(t.thisAccount.details.particulars)), O.getOrElse(() => t.type.description)); const convertTransactions = (ynabAccountID) => (transactions) => { // Sort oldest -> newest for import ID counters transactions = transactions.reverse(); const importID = __1.Ynab.importID(); const convert = (t) => { const date = dateTime(t.timestamp); const amount = __1.Ynab.amountFromString(t.value.amount); const import_id = importID(date, amount); const memo = memoFromTransaction(t); const payee_name = payeeFromTransaction(t); return { account_id: ynabAccountID, amount, date: date.toISODate(), import_id, memo, payee_name, }; }; return transactions.map(convert); }; const ynabTransactions = (page) => (accounts) => (includePending) => (accountName, ynabAccountID) => F.pipe(findAccount(accounts)(accountName), O.fold(() => Promise.resolve([]), account => listTransactions(page)(account.id) .then(r => r.transactions) .then(filterFuture) .then(includePending ? filterPendingInternational : filterPending) .then(convertTransactions(ynabAccountID)))); const bnzAdapter = async ({ accessNumber, password, includePending = false, }) => { const { browser, page } = await (0, __1.setupPage)(); await login(page)(accessNumber, password); const accounts = await getAccounts(page); return [ ynabTransactions(page)(accounts)(includePending), () => browser.close(), ]; }; exports.bnzAdapter = bnzAdapter; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYWRhcHRlcnMvYm56L2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsa0RBQW9DO0FBQ3BDLGdEQUFrQztBQUNsQyxpQ0FBaUM7QUFHakMsOEJBQW1EO0FBR25ELE1BQU0sS0FBSyxHQUFHLENBQUMsSUFBVSxFQUFFLEVBQUUsQ0FBQyxLQUFLLEVBQ2pDLFlBQW9CLEVBQ3BCLFFBQWdCLEVBQ2hCLE9BQU8sR0FBRyxDQUFDLEVBQ1gsRUFBRTtJQUNGLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5QixNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsOENBQThDLENBQUMsQ0FBQztJQUNoRSxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsdUJBQXVCLEVBQUUsWUFBWSxDQUFDLENBQUM7SUFDdkQsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLHlCQUF5QixFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ3JELE1BQU0sSUFBSSxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0lBRXhDLElBQUk7UUFDRixNQUFNLEVBQUUsR0FBRyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUM7WUFDNUIsSUFBSSxDQUFDLGVBQWUsQ0FBQywrQkFBK0IsQ0FBQztZQUNyRCxJQUFJLENBQUMsZUFBZSxDQUFDLHFCQUFxQixDQUFDO1NBQzVDLENBQUMsQ0FBQztRQUVILElBQUksRUFBRSxFQUFFO1lBQ04sTUFBTSxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7U0FDbEI7UUFDRCxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsK0JBQStCLENBQUMsQ0FBQztLQUM3RDtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1YsSUFBSSxPQUFPLEdBQUcsQ0FBQyxFQUFFO1lBQ2YsTUFBTSxDQUFDLENBQUM7U0FDVDtRQUNE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