All files / packages/gemini-core/src/mcp/token-storage base-token-storage.ts

13.33% Statements 2/15
0% Branches 0/5
25% Functions 1/4
13.33% Lines 2/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49                6x       6x                                                                        
/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
 
import type { TokenStorage, OAuthCredentials } from './types';
 
export abstract class BaseTokenStorage implements TokenStorage {
  protected readonly serviceName: string;
 
  constructor(serviceName: string) {
    this.serviceName = serviceName;
  }
 
  abstract getCredentials(serverName: string): Promise<OAuthCredentials | null>;
  abstract setCredentials(credentials: OAuthCredentials): Promise<void>;
  abstract deleteCredentials(serverName: string): Promise<void>;
  abstract listServers(): Promise<string[]>;
  abstract getAllCredentials(): Promise<Map<string, OAuthCredentials>>;
  abstract clearAll(): Promise<void>;
 
  protected validateCredentials(credentials: OAuthCredentials): void {
    Iif (!credentials.serverName) {
      throw new Error('Server name is required');
    }
    Iif (!credentials.token) {
      throw new Error('Token is required');
    }
    Iif (!credentials.token.accessToken) {
      throw new Error('Access token is required');
    }
    Iif (!credentials.token.tokenType) {
      throw new Error('Token type is required');
    }
  }
 
  protected isTokenExpired(credentials: OAuthCredentials): boolean {
    Iif (!credentials.token.expiresAt) {
      return false;
    }
    const bufferMs = 5 * 60 * 1000;
    return Date.now() > credentials.token.expiresAt - bufferMs;
  }
 
  protected sanitizeServerName(serverName: string): string {
    return serverName.replace(/[^a-zA-Z0-9-_.]/g, '_');
  }
}