<commit_before>import type {
  RefreshTokenRequest,
  TokenFinalResponse,
} from 'dexie-cloud-common';
import { b64encode } from 'dreambase-library/dist/common/base64';
import { BehaviorSubject } from 'rxjs';
import { DexieCloudDB } from '../db/DexieCloudDB';
import { UserLogin } from '../db/entities/UserLogin';
import { DXCAlert } from '../types/DXCAlert';
import {
  DXCMessageAlert,
  DXCUserInteraction,
} from '../types/DXCUserInteraction';
import { alertUser, interactWithUser } from './interactWithUser';

export type FetchTokenCallback = (tokenParams: {
  public_key: string;
  hints?: { userId?: string; email?: string; grant_type?: string };
}) => Promise<TokenFinalResponse>;

export async function loadAccessToken(
  db: DexieCloudDB
): Promise<string | undefined> {
  const {
    accessToken,
    accessTokenExpiration,
    refreshToken,
    refreshTokenExpiration,
    claims,
  } = db.cloud.currentUser.value;
  if (!accessToken) return;
  const expTime = accessTokenExpiration?.getTime() ?? Infinity;
  if (expTime > Date.now()) {
    return accessToken;
  }
  if (!refreshToken) {
    throw new Error(`Refresh token missing`);
  }
  const refreshExpTime = refreshTokenExpiration?.getTime() ?? Infinity;
  if (refreshExpTime <= Date.now()) {
    throw new Error(`Refresh token has expired`);
  }
  const refreshedLogin = await refreshAccessToken(
    db.cloud.options!.databaseUrl,
    db.cloud.currentUser.value
  );
  await db.table('$logins').update(claims.sub, {
    accessToken: refreshedLogin.accessToken,
    accessTokenExpiration: refreshedLogin.accessTokenExpiration,
  });
  return refreshedLogin.accessToken;
}

export async function authenticate(
  url: string,
  context: UserLogin,
  fetchToken: FetchTokenCallback,
  userInteraction: BehaviorSubject<DXCUserInteraction | undefined>,
  hints?: { userId?: string; email?: string; grant_type?: string }
): Promise<UserLogin> {
  if (
    context.accessToken &&
    context.accessTokenExpiration!.getTime() > Date.now()
  ) {
    return context;
  } else if (<commit_msg>Don't rely on db.cloud.currentUser in SW sync as that observable isn't up-to-date in service workers.<commit_after>import type {
  RefreshTokenRequest,
  TokenFinalResponse,
} from 'dexie-cloud-common';
import { b64encode } from 'dreambase-library/dist/common/base64';
import { BehaviorSubject } from 'rxjs';
import { DexieCloudDB } from '../db/DexieCloudDB';
import { UserLogin } from '../db/entities/UserLogin';
import { DXCAlert } from '../types/DXCAlert';
import {
  DXCMessageAlert,
  DXCUserInteraction,
} from '../types/DXCUserInteraction';
import { alertUser, interactWithUser } from './interactWithUser';

export type FetchTokenCallback = (tokenParams: {
  public_key: string;
  hints?: { userId?: string; email?: string; grant_type?: string };
}) => Promise<TokenFinalResponse>;

export async function loadAccessToken(
  db: DexieCloudDB
): Promise<string | undefined> {
  const currentUser = await db.getCurrentUser();
  const {
    accessToken,
    accessTokenExpiration,
    refreshToken,
    refreshTokenExpiration,
    claims,
  } = currentUser;
  if (!accessToken) return;
  const expTime = accessTokenExpiration?.getTime() ?? Infinity;
  if (expTime > Date.now()) {
    return accessToken;
  }
  if (!refreshToken) {
    throw new Error(`Refresh token missing`);
  }
  const refreshExpTime = refreshTokenExpiration?.getTime() ?? Infinity;
  if (refreshExpTime <= Date.now()) {
    throw new Error(`Refresh token has expired`);
  }
  const refreshedLogin = await refreshAccessToken(
    db.cloud.options!.databaseUrl,
    currentUser
  );
  await db.table('$logins').update(claims.sub, {
    accessToken: refreshedLogin.accessToken,
    accessTokenExpiration: refreshedLogin.accessTokenExpiration,
  });
  return refreshedLogin.accessToken;
}

export async function authenticate(
  url: string,
  context: UserLogin,
  fetchToken: FetchTokenCallback,
  userInteraction: BehaviorSubject<DXCUserInteraction | undefined>,
  hints?: { userId?: string; email?: string; grant_type?: string }
): Promise<UserLogin> {
  if (
    context.accessToken &&
    context.accessTokenExpiration!.getTime() > Date.now()
  ) {
    return context;
  } else if (
{'fraction_non_alphanumeric': 0.12217732350843832, 'fraction_numerical': 0.0019015925837889231, 'mean_word_length': 4.536842105263158, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1558385', 'n_tokens_mistral': 1295, 'n_tokens_neox': 1269, 'n_words': 298}