/**
* Token storage and persistence utility.
* Stores session tokens to disk for persistence and auto-reconnect.
*/
import { promises as fs } from 'fs';
import { homedir } from 'os';
import { join } from 'path';
import { TokenData } from '../types/index.js';
import { logger } from './logger.js';
const TOKEN_DIR = join(homedir(), '.mcp-wppconnect', 'tokens');
class TokenStorage {
/**
* Save a token to disk.
*/
async save(sessionId: string, token: TokenData): Promise<void> {
try {
await fs.mkdir(TOKEN_DIR, { recursive: true });
const filePath = join(TOKEN_DIR, `${sessionId}.json`);
const content = JSON.stringify(token, null, 2);
await fs.writeFile(filePath, content, 'utf-8');
logger.info('TokenStorage.save', `Token saved for session ${sessionId}`);
} catch (error) {
logger.error('TokenStorage.save', error);
throw error;
}
}
/**
* Load a token from disk.
*/
async load(sessionId: string): Promise<TokenData | null> {
try {
const filePath = join(TOKEN_DIR, `${sessionId}.json`);
const content = await fs.readFile(filePath, 'utf-8');
const token = JSON.parse(content) as TokenData;
logger.info('TokenStorage.load', `Token loaded for session ${sessionId}`);
return token;
} catch (error) {
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
logger.debug('TokenStorage.load', `Token not found for session ${sessionId}`);
return null;
}
logger.error('TokenStorage.load', error);
return null;
}
}
/**
* Check if a token exists.
*/
async exists(sessionId: string): Promise<boolean> {
try {
const filePath = join(TOKEN_DIR, `${sessionId}.json`);
await fs.access(filePath);
return true;
} catch {
return false;
}
}
/**
* Delete a token from disk.
*/
async delete(sessionId: string): Promise<void> {
try {
const filePath = join(TOKEN_DIR, `${sessionId}.json`);
await fs.unlink(filePath);
logger.info('TokenStorage.delete', `Token deleted for session ${sessionId}`);
} catch (error) {
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
logger.debug('TokenStorage.delete', `Token not found for session ${sessionId}`);
return;
}
logger.error('TokenStorage.delete', error);
}
}
/**
* List all saved session IDs.
*/
async listSessions(): Promise<string[]> {
try {
const files = await fs.readdir(TOKEN_DIR);
return files
.filter((file) => file.endsWith('.json'))
.map((file) => file.replace('.json', ''));
} catch (error) {
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
logger.debug('TokenStorage.listSessions', 'Token directory does not exist');
return [];
}
logger.error('TokenStorage.listSessions', error);
return [];
}
}
}
export const tokenStorage = new TokenStorage();