diff options
Diffstat (limited to 'app/src/lib/server/sb1.ts')
| -rw-r--r-- | app/src/lib/server/sb1.ts | 85 |
1 files changed, 71 insertions, 14 deletions
diff --git a/app/src/lib/server/sb1.ts b/app/src/lib/server/sb1.ts index a7cad3e..f6507ef 100644 --- a/app/src/lib/server/sb1.ts +++ b/app/src/lib/server/sb1.ts @@ -4,6 +4,7 @@ import { Temporal } from "temporal-polyfill"; import { randomUUID } from "node:crypto"; import { db } from "./db"; import { syncSession } from "./db/schema"; +import { add_session_log } from "./session-log"; export type Sb1Tokens = { access_token: string @@ -14,12 +15,12 @@ export type Sb1Tokens = { refresh_token: string } -export type Transaction = { +export type Sb1Transaction = { id: string nonUniqueId: string description: string cleanedDescription: string - accountNumber: AccountNumber + accountNumber: Sb1AccountNumber amount: number date: number interestDate: number @@ -34,16 +35,44 @@ export type Transaction = { accountKey: string accountCurrency: string isFromCurrencyAccount: boolean - classificationInput: ClassificationInput + classificationInput: Sb1ClassificationInput } -export type AccountNumber = { +export type Sb1Account = { + key: string; + accountNumber: string; + iban: string; + name: string; + description: string; + balance: number; + availableBalance: number; + currencyCode: string; + owner: Sb1AccountOwner; + productType: string; + type: string; + productId: string; + descriptionCode: string; + accountProperties: { [key: string]: boolean }; +} + +export type Sb1AccountOwner = { + name: string; + firstName: string; + lastName: string; + type: string; + age: number; + customerKey: string; + ssnKey: string; +} + + +export type Sb1AccountNumber = { value: string formatted: string unformatted: string } -export type ClassificationInput = { +export type Sb1ClassificationInput = { id: string amount: number type: string @@ -139,12 +168,13 @@ const auth = { const epoch = Temporal.Now.instant().epochMilliseconds if (res.ok) { await db.update(syncSession).set({ tokens, accessTokenCreated: epoch.toString(), refreshTokenCreated: epoch.toString() }).where(eq(syncSession.id, id)) + await add_session_log(id, "REFRESH_SB1_TOKEN", "Done") return tokens } else { console.error("Failed to refresh tokens", tokens) + await add_session_log(id, "REFRESH_SB1_TOKEN", "Failed: " + JSON.stringify(res)) return null } - } } @@ -160,23 +190,50 @@ const data = { Authorization: `Bearer ${token}` } }) - if (response.ok) return await response.json() as { accounts: Array<any> } + if (response.ok) return await response.json() as { accounts: Array<Sb1Account> } else console.error(await response.text()) }, - async get_transactions(accountKey: string) { + async get_transactions(accountKey: string, delta?: Temporal.Instant) { const token = await auth.get_access_token() + if (!token) return undefined - const response = await fetch("https://api.sparebank1.no/personal/banking/transactions?" + new URLSearchParams({ - "accountKey": accountKey - }), { + const params = new URLSearchParams({ + "accountKey": accountKey, + }); + if (delta) params.append("fromDate", formatInstant(delta, "yyyy-MM-dd")) + const response = await fetch("https://api.sparebank1.no/personal/banking/transactions?" + params, { headers: { Authorization: `Bearer ${token}`, }, }); const json = await response.json() - console.log(accountKey + ":" + json["transactions"]?.length) - return json["transactions"] as Transaction[]; + return json["transactions"] as Sb1Transaction[]; } } -export default { auth, data }
\ No newline at end of file +export default { auth, data } + +export function formatInstant( + instant: Temporal.Instant, + format: string, + timeZone: string = "UTC" +): string { + const zdt = instant.toZonedDateTimeISO(timeZone); + + const pad = (value: number, length = 2) => + value.toString().padStart(length, "0"); + + const replacements: Record<string, string> = { + yyyy: pad(zdt.year, 4), + MM: pad(zdt.month), + dd: pad(zdt.day), + HH: pad(zdt.hour), + mm: pad(zdt.minute), + ss: pad(zdt.second), + }; + + return format.replace( + /yyyy|MM|dd|HH|mm|ss/g, + (token) => replacements[token] + ); +} |
