diff options
Diffstat (limited to 'app/src')
| -rw-r--r-- | app/src/hooks.server.ts | 3 | ||||
| -rw-r--r-- | app/src/lib/server/sb1.ts | 89 | ||||
| -rw-r--r-- | app/src/routes/sb1.remote.ts | 2 |
3 files changed, 70 insertions, 24 deletions
diff --git a/app/src/hooks.server.ts b/app/src/hooks.server.ts new file mode 100644 index 0000000..739ef2b --- /dev/null +++ b/app/src/hooks.server.ts @@ -0,0 +1,3 @@ +export async function handleFetch({ event, request, fetch }) { + return await fetch(request); +}
\ No newline at end of file diff --git a/app/src/lib/server/sb1.ts b/app/src/lib/server/sb1.ts index 1d6b869..b456609 100644 --- a/app/src/lib/server/sb1.ts +++ b/app/src/lib/server/sb1.ts @@ -14,11 +14,41 @@ type Sb1Tokens = { refresh_token: string } -type Transaction = { +export type Transaction = { + id: string + nonUniqueId: string description: string + cleanedDescription: string + accountNumber: AccountNumber amount: number + date: number + interestDate: number + typeCode: string + typeText: string + currencyCode: string + canShowDetails: boolean + source: string + isConfidential: boolean + bookingStatus: string + accountName: string + accountKey: string + accountCurrency: string + isFromCurrencyAccount: boolean + classificationInput: ClassificationInput +} + +export type AccountNumber = { + value: string + formatted: string + unformatted: string +} + +export type ClassificationInput = { + id: string + amount: number + type: string + text: string date: string - mcc: string } const auth = { @@ -60,15 +90,28 @@ const auth = { return authorizeUrl.toString() }, async get_access_token() { - const entity = await db.select({ - tokens: syncSession.tokens + const result = await db.select({ + tokens: syncSession.tokens, + refreshTokenCreated: syncSession.refreshTokenCreated, + accessTokenCreated: syncSession.accessTokenCreated }).from(syncSession) - const res = entity[0] - if (!res?.tokens) return null - const parsed = JSON.parse(res.tokens) as Sb1Tokens - return parsed.access_token as string + const { tokens: _tokens, accessTokenCreated, refreshTokenCreated } = result[0] + let tokens = JSON.parse(_tokens ?? "") as Sb1Tokens + const nowInstant = Temporal.Now.instant() + const accessTokenExpiredInstant = Temporal.Instant.fromEpochMilliseconds(accessTokenCreated ?? 0).add({ seconds: tokens.expires_in }) + if (Temporal.Instant.compare(nowInstant, accessTokenExpiredInstant) >= 0) { + const refreshedTokens = await this.refresh_token() + if (refreshedTokens) return refreshedTokens.access_token + } + const refreshTokenExpiredInstant = Temporal.Instant.fromEpochMilliseconds(refreshTokenCreated ?? 0).add({ seconds: tokens.refresh_token_expires_in }) + if (Temporal.Instant.compare(nowInstant, refreshTokenExpiredInstant) >= 0) { + return undefined + } + + return tokens?.access_token as string }, - async refresh_tokem() { + async refresh_token(): Promise<Sb1Tokens | null> { + console.log("Refreshing tokens") const entity = await db.select({ tokens: syncSession.tokens, id: syncSession.id @@ -96,10 +139,16 @@ const auth = { method: "POST", body: params, }); - - const text = await res.text(); + const text = await res.text() const epoch = Temporal.Now.instant().epochMilliseconds - await db.update(syncSession).set({ tokens: text, accessTokenCreated: epoch, refreshTokenCreated: epoch }).where(eq(syncSession.id, id)) + if (res.ok) { + await db.update(syncSession).set({ tokens: text, accessTokenCreated: epoch, refreshTokenCreated: epoch }).where(eq(syncSession.id, id)) + return JSON.parse(text) as Sb1Tokens + } else { + console.error("Failed to refresh tokens", text) + return null + } + } } @@ -120,23 +169,17 @@ const data = { }, async get_transactions(accountKey: string) { const token = await auth.get_access_token() - if (token) return undefined - const url = new URL("https://api.sparebank1.no/personal/banking/transactions/transactions") - console.log(token) - url.searchParams.set("accountKey", accountKey); - console.log(accountKey) - const response = await fetch("https://api.sparebank1.no/personal/banking/transactions" + new URLSearchParams({ - "accountKey": accountKey, - "fromDate": "", - "toDate": "" + if (!token) return undefined + const response = await fetch("https://api.sparebank1.no/personal/banking/transactions?" + new URLSearchParams({ + "accountKey": accountKey }), { headers: { Authorization: `Bearer ${token}`, }, }); const json = await response.json() - return (await response.json())["transactions"] as Transaction[]; - + console.log(accountKey + ":" + json["transactions"]?.length) + return json["transactions"] as Transaction[]; } } diff --git a/app/src/routes/sb1.remote.ts b/app/src/routes/sb1.remote.ts index c3967c1..9a2167e 100644 --- a/app/src/routes/sb1.remote.ts +++ b/app/src/routes/sb1.remote.ts @@ -29,7 +29,7 @@ const get_auth_info = query(() => { }) const refresh_tokem = command(async () => { - await sb1.auth.refresh_tokem() + await sb1.auth.refresh_token() }) export { |
