import Database from "better-sqlite3" import dayjs from "dayjs" import type { OAuthTokenResponse } from "@sb1/types.ts" import type { TokenKey, TokenResponse, TokenResponseRaw, } from "@sb1impl/db/types.ts" import logger from "@common/logger.ts" export function createDb(filepath: string) { const db = new Database(filepath) logger.info(`Started Sqlite database at '${filepath}'`) db.pragma("journal_mode = WAL") db.exec( "CREATE TABLE IF NOT EXISTS tokens ('key' VARCHAR PRIMARY KEY, token VARCHAR NOT NULL, expires_at DATETIME NOT NULL)", ) return db } export function insertTokens( db: Database.Database, oAuthToken: OAuthTokenResponse, ): void { insertAccessToken(db, oAuthToken.access_token, oAuthToken.expires_in) insertRefreshToken( db, oAuthToken.refresh_token, oAuthToken.refresh_token_absolute_expires_in, ) } function insertAccessToken( db: Database.Database, accessToken: string, expiresIn: number, ) { insert(db, "access-token", accessToken, expiresIn) } function insertRefreshToken( db: Database.Database, refreshToken: string, expiresIn: number, ): void { insert(db, "refresh-token", refreshToken, expiresIn) } function insert( db: Database.Database, key: TokenKey, token: string, expiresIn: number, ): void { db.prepare("INSERT OR REPLACE INTO tokens VALUES (?, ?, ?)").run( key, token, dayjs().add(expiresIn, "seconds").toISOString(), ) } export function fetchToken( db: Database.Database, tokenKey: TokenKey, ): TokenResponse | null { const response = db .prepare("SELECT * FROM tokens WHERE key = ?") .get(tokenKey) as TokenResponseRaw | null return ( response && { ...response, expires_at: dayjs(response.expires_at), } ) } export function clearTokens(db: Database.Database): void { db.prepare("DELETE FROM tokens WHERE key in ( ?, ? )").run([ "access-token", "refresh-token", ] as TokenKey[]) }