Added:
- Logging library - Account Ids to .env - Split logic in main function
This commit is contained in:
53
src/main.ts
53
src/main.ts
@ -1,32 +1,47 @@
|
||||
import { type Actual, ActualImpl } from "@/actual.ts"
|
||||
import { cronJobDaily } from "@/cron.ts"
|
||||
import { type Bank, Sparebank1Impl } from "@/sparebank1.ts"
|
||||
import { type Bank, Sparebank1Impl, type Transaction } from "@/sparebank1.ts"
|
||||
import { transactionIntoActualTransaction } from "@/mappings.ts"
|
||||
import { ACTUAL_ACCOUNT_IDS, BANK_ACCOUNT_IDS } from "../config.ts"
|
||||
import logger from "pino"
|
||||
import type { UUID } from "node:crypto"
|
||||
|
||||
async function daily(actual: Actual, bank: Bank): Promise<() => Promise<void>> {
|
||||
return async () => {
|
||||
console.log("Wake up! It's 1 AM!")
|
||||
// Fetch transactions from the bank
|
||||
const transactions = await bank.transactionsPastDay(
|
||||
"my_account",
|
||||
"my_access_token",
|
||||
)
|
||||
// TODO Transports api for pino https://github.com/pinojs/pino/blob/HEAD/docs/transports.md
|
||||
|
||||
// TODO account? id or name?
|
||||
const actualTransactions = transactions.map((transaction) =>
|
||||
transactionIntoActualTransaction(transaction, ""),
|
||||
)
|
||||
async function daily(actual: Actual, bank: Bank): Promise<void> {
|
||||
// Fetch transactions from the bank
|
||||
const transactions = await fetchTransactionsFromPastDay(bank)
|
||||
logger().info(`Fetched ${transactions.length} transactions`)
|
||||
|
||||
// TODO Import transactions into Actual
|
||||
// If multiple accounts, loop over them
|
||||
// Get account ID from mapper
|
||||
await actual.importTransactions("a-b-c-d-e", actualTransactions)
|
||||
}
|
||||
// TODO multiple accounts
|
||||
const accountId = ACTUAL_ACCOUNT_IDS[0] as UUID
|
||||
const actualTransactions = transactions.map((transaction) =>
|
||||
transactionIntoActualTransaction(transaction, accountId),
|
||||
)
|
||||
|
||||
// TODO Import transactions into Actual
|
||||
// If multiple accounts, loop over them
|
||||
// Get account ID from mapper
|
||||
await actual.importTransactions(accountId, actualTransactions)
|
||||
}
|
||||
|
||||
async function fetchTransactionsFromPastDay(
|
||||
bank: Bank,
|
||||
): Promise<ReadonlyArray<Transaction>> {
|
||||
// TODO refresh token
|
||||
const { access_token } = await bank.refreshToken("my_refresh_token")
|
||||
return bank.transactionsPastDay(BANK_ACCOUNT_IDS, access_token)
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
logger().info("Starting application")
|
||||
const actual = await ActualImpl.init()
|
||||
cronJobDaily(await daily(actual, new Sparebank1Impl()))
|
||||
cronJobDaily(async () => {
|
||||
logger().info("Running daily job")
|
||||
await daily(actual, new Sparebank1Impl())
|
||||
logger().info("Finished daily job")
|
||||
})
|
||||
logger().info("Shutting down")
|
||||
// await actual.shutdown()
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,15 @@
|
||||
import type { Transaction } from "@/sparebank1.ts"
|
||||
import type { TransactionEntity } from "@actual-app/api/@types/loot-core/types/models"
|
||||
import type { UUID } from "node:crypto"
|
||||
|
||||
// TODO more fields / correct fields?
|
||||
export function transactionIntoActualTransaction(
|
||||
transaction: Transaction,
|
||||
account: string,
|
||||
accountId: UUID,
|
||||
): TransactionEntity {
|
||||
return {
|
||||
id: transaction.id,
|
||||
account,
|
||||
account: accountId,
|
||||
amount: transaction.amount,
|
||||
date: transaction.date,
|
||||
payee: transaction.description,
|
||||
|
@ -1,9 +1,3 @@
|
||||
import {
|
||||
SPAREBANK1_OAUTH_CLIENT_ID,
|
||||
SPAREBANK1_OAUTH_REDIRECT_URI,
|
||||
SPAREBANK1_OAUTH_STATE,
|
||||
} from "../config.ts"
|
||||
|
||||
// TODO move types
|
||||
export interface OAuthTokenResponse {
|
||||
access_token: string
|
||||
@ -40,18 +34,14 @@ export interface Sparebank1 {
|
||||
export class Sparebank1Impl implements Sparebank1 {
|
||||
private baseUrl = "https://api.sparebank1.no"
|
||||
|
||||
// TODO remove?
|
||||
async accessToken(): Promise<OAuthTokenResponse> {
|
||||
const response = await fetch(`${this.baseUrl}/oauth/authorize?
|
||||
client_id=${SPAREBANK1_OAUTH_CLIENT_ID}&
|
||||
state=${SPAREBANK1_OAUTH_STATE}&
|
||||
redirect_uri=${SPAREBANK1_OAUTH_REDIRECT_URI}&
|
||||
finInst=fid-smn&
|
||||
response_type=code`)
|
||||
throw new Error("Not implemented")
|
||||
|
||||
if (response.ok) {
|
||||
return await response.json()
|
||||
}
|
||||
throw new Error(`Failed to get access token. ${response.statusText}`)
|
||||
// if (response.ok) {
|
||||
// return await response.json()
|
||||
// }
|
||||
// throw new Error(`Failed to get access token. ${response.statusText}`)
|
||||
}
|
||||
|
||||
async refreshToken(refreshToken: string): Promise<OAuthTokenResponse> {
|
||||
|
Reference in New Issue
Block a user