chore(ts): wave 4c — type 8 files (components, SSE handlers, services) 313→252

This commit is contained in:
diegosouzapw
2026-02-17 06:13:11 -03:00
parent 7729896dc2
commit ccd4ab6c8d
8 changed files with 103 additions and 103 deletions

View File

@@ -29,9 +29,9 @@ export default function ModelSelectModal({
modelAliases = {},
}) {
const [searchQuery, setSearchQuery] = useState("");
const [combos, setCombos] = useState([]);
const [providerNodes, setProviderNodes] = useState([]);
const [customModels, setCustomModels] = useState({});
const [combos, setCombos] = useState<any[]>([]);
const [providerNodes, setProviderNodes] = useState<any[]>([]);
const [customModels, setCustomModels] = useState<Record<string, any>>({});
const fetchCombos = async () => {
try {
@@ -88,7 +88,7 @@ export default function ModelSelectModal({
// Group models by provider with priority order
const groupedModels = useMemo(() => {
const groups = {};
const groups: Record<string, any> = {};
// Get all active provider IDs from connections
const activeConnectionIds = activeProviders.map((p) => p.provider);
@@ -115,9 +115,9 @@ export default function ModelSelectModal({
const providerCustomModels = customModels[providerId] || [];
if (providerInfo.passthroughModels) {
const aliasModels = Object.entries(modelAliases)
.filter(([, fullModel]) => fullModel.startsWith(`${alias}/`))
.map(([aliasName, fullModel]) => ({
const aliasModels = Object.entries(modelAliases as Record<string, string>)
.filter(([, fullModel]: [string, string]) => fullModel.startsWith(`${alias}/`))
.map(([aliasName, fullModel]: [string, string]) => ({
id: fullModel.replace(`${alias}/`, ""),
name: aliasName,
value: fullModel,
@@ -150,9 +150,9 @@ export default function ModelSelectModal({
const matchedNode = providerNodes.find((node) => node.id === providerId);
const displayName = matchedNode?.name || providerInfo.name;
const nodeModels = Object.entries(modelAliases)
.filter(([, fullModel]) => fullModel.startsWith(`${providerId}/`))
.map(([aliasName, fullModel]) => ({
const nodeModels = Object.entries(modelAliases as Record<string, string>)
.filter(([, fullModel]: [string, string]) => fullModel.startsWith(`${providerId}/`))
.map(([aliasName, fullModel]: [string, string]) => ({
id: fullModel.replace(`${providerId}/`, ""),
name: aliasName,
value: fullModel,
@@ -227,9 +227,9 @@ export default function ModelSelectModal({
if (!searchQuery.trim()) return groupedModels;
const query = searchQuery.toLowerCase();
const filtered = {};
const filtered: Record<string, any> = {};
Object.entries(groupedModels).forEach(([providerId, group]) => {
Object.entries(groupedModels).forEach(([providerId, group]: [string, any]) => {
const matchedModels = group.models.filter(
(m) => m.name.toLowerCase().includes(query) || m.id.toLowerCase().includes(query)
);
@@ -247,7 +247,7 @@ export default function ModelSelectModal({
return filtered;
}, [groupedModels, searchQuery]);
const handleSelect = (model) => {
const handleSelect = (model: any) => {
onSelect(model);
onClose();
setSearchQuery("");
@@ -317,7 +317,7 @@ export default function ModelSelectModal({
)}
{/* Provider models */}
{Object.entries(filteredGroups).map(([providerId, group]) => (
{Object.entries(filteredGroups).map(([providerId, group]: [string, any]) => (
<div key={providerId}>
{/* Provider header */}
<div className="flex items-center gap-1.5 mb-1.5 sticky top-0 bg-surface py-0.5">

View File

@@ -23,9 +23,9 @@ import {
export default function UsageAnalytics() {
const [range, setRange] = useState("30d");
const [analytics, setAnalytics] = useState(null);
const [analytics, setAnalytics] = useState<any>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [error, setError] = useState<string | null>(null);
const fetchAnalytics = useCallback(async () => {
try {
@@ -36,7 +36,7 @@ export default function UsageAnalytics() {
setAnalytics(data);
setError(null);
} catch (err) {
setError(err.message);
setError((err as any).message);
} finally {
setLoading(false);
}

View File

@@ -8,7 +8,7 @@ import Badge from "./Badge";
import { CardSkeleton } from "./Loading";
import { fmtFull, fmtCost } from "@/shared/utils/formatting";
function SortIcon({ field, currentSort, currentOrder }) {
function SortIcon({ field, currentSort, currentOrder }: { field: string; currentSort: string; currentOrder: string }) {
if (currentSort !== field) return <span className="ml-1 opacity-20"></span>;
return <span className="ml-1">{currentOrder === "asc" ? "↑" : "↓"}</span>;
}
@@ -19,7 +19,7 @@ SortIcon.propTypes = {
currentOrder: PropTypes.string.isRequired,
};
function MiniBarGraph({ data, colorClass = "bg-primary" }) {
function MiniBarGraph({ data, colorClass = "bg-primary" }: { data: number[]; colorClass?: string }) {
const max = Math.max(...data, 1);
return (
<div className="flex items-end gap-1 h-8 w-24">
@@ -47,14 +47,14 @@ export default function UsageStats() {
const sortBy = searchParams.get("sortBy") || "rawModel";
const sortOrder = searchParams.get("sortOrder") || "asc";
const [stats, setStats] = useState(null);
const [stats, setStats] = useState<any>(null);
const [loading, setLoading] = useState(true);
const [autoRefresh, setAutoRefresh] = useState(true);
const [viewMode, setViewMode] = useState("tokens"); // 'tokens' or 'costs'
const [refreshInterval, setRefreshInterval] = useState(5000); // Start with 5s
const prevTotalRequestsRef = useRef(0);
const toggleSort = (field) => {
const toggleSort = (field: string) => {
const params = new URLSearchParams(searchParams.toString());
if (sortBy === field) {
params.set("sortOrder", sortOrder === "asc" ? "desc" : "asc");
@@ -66,9 +66,9 @@ export default function UsageStats() {
};
const sortData = useCallback(
(dataMap, pendingMap = {}) => {
(dataMap: Record<string, any>, pendingMap: Record<string, any> = {}) => {
return Object.entries(dataMap || {})
.map(([key, data]) => {
.map(([key, data]: [string, any]) => {
const totalTokens = (data.promptTokens || 0) + (data.completionTokens || 0);
const totalCost = data.cost || 0;
@@ -111,9 +111,9 @@ export default function UsageStats() {
const sortedAccounts = useMemo(() => {
// For accounts, pendingMap is by connectionId, but dataMap is by accountKey
// We need to map connectionId pending counts to accountKeys
const accountPendingMap = {};
const accountPendingMap: Record<string, any> = {};
if (stats?.pending?.byAccount) {
Object.entries(stats.byAccount || {}).forEach(([accountKey, data]) => {
Object.entries(stats.byAccount || {}).forEach(([accountKey, data]: [string, any]) => {
const connPending = stats.pending.byAccount[data.connectionId];
if (connPending) {
// Get modelKey (rawModel (provider))
@@ -125,7 +125,7 @@ export default function UsageStats() {
return sortData(stats?.byAccount, accountPendingMap);
}, [stats?.byAccount, stats?.pending?.byAccount, sortData]);
const fetchStats = useCallback(async (showLoading = true) => {
const fetchStats = useCallback(async (showLoading = true): Promise<void> => {
if (showLoading) setLoading(true);
try {
const res = await fetch("/api/usage/history");
@@ -156,7 +156,7 @@ export default function UsageStats() {
}, [fetchStats]);
useEffect(() => {
let intervalId;
let intervalId: ReturnType<typeof setInterval> | undefined;
let isPageVisible = true;
// Page Visibility API - pause when tab is hidden
@@ -191,16 +191,16 @@ export default function UsageStats() {
if (!stats) return <div className="text-text-muted">Failed to load usage statistics.</div>;
// Format number with commas — delegated to shared module
const fmt = (n) => fmtFull(n);
const fmt = (n: number) => fmtFull(n);
// Format cost with dollar sign and 2 decimals — delegated to shared module
// Time format for "Last Used"
const fmtTime = (iso) => {
const fmtTime = (iso: string) => {
if (!iso) return "Never";
const date = new Date(iso);
const now = new Date();
const diffMs = now - date;
const diffMs = now.getTime() - date.getTime();
const diffMins = Math.floor(diffMs / 60000);
if (diffMins < 1) return "Just now";
@@ -459,7 +459,7 @@ export default function UsageStats() {
{data.rawModel}
</td>
<td className="px-6 py-3">
<Badge variant={data.pending > 0 ? "primary" : "neutral"} size="sm">
<Badge variant={data.pending > 0 ? "primary" : "default"} size="sm">
{data.provider}
</Badge>
</td>
@@ -625,7 +625,7 @@ export default function UsageStats() {
{data.rawModel}
</td>
<td className="px-6 py-3">
<Badge variant={data.pending > 0 ? "primary" : "neutral"} size="sm">
<Badge variant={data.pending > 0 ? "primary" : "default"} size="sm">
{data.provider}
</Badge>
</td>

View File

@@ -25,7 +25,7 @@ import {
// ── Custom Tooltip for dark theme ──────────────────────────────────────────
function DarkTooltip({ active, payload, label, formatter }) {
function DarkTooltip({ active, payload, label, formatter }: { active?: boolean; payload?: any[]; label?: any; formatter?: Function }) {
if (!active || !payload?.length) return null;
return (
<div className="rounded-lg border border-white/10 bg-surface px-3 py-2 text-xs shadow-lg">
@@ -48,7 +48,7 @@ function DarkTooltip({ active, payload, label, formatter }) {
// ── Sort Indicator (shared by tables) ──────────────────────────────────────
export function SortIndicator({ active, sortOrder }) {
export function SortIndicator({ active, sortOrder }: { active: boolean; sortOrder: string }) {
if (!active) {
return (
<span className="material-symbols-outlined text-[12px] opacity-0 group-hover:opacity-30">
@@ -65,7 +65,7 @@ export function SortIndicator({ active, sortOrder }) {
// ── StatCard ───────────────────────────────────────────────────────────────
export function StatCard({ icon, label, value, subValue, color = "text-text-main" }) {
export function StatCard({ icon, label, value, subValue, color = "text-text-main" }: { icon: any; label: any; value: any; subValue?: any; color?: string }) {
return (
<Card className="px-4 py-3 flex flex-col gap-1">
<div className="flex items-center gap-2 text-text-muted text-xs uppercase font-semibold tracking-wider">
@@ -161,7 +161,7 @@ export function ActivityHeatmap({ activityMap }) {
<h3 className="text-sm font-semibold text-text-muted uppercase tracking-wider">Activity</h3>
<span className="text-xs text-text-muted">
{Object.keys(activityMap || {}).length} active days ·{" "}
{fmt(Object.values(activityMap || {}).reduce((a, b) => a + b, 0))} tokens · 365 days
{fmt(Object.values(activityMap || {}).reduce((a: number, b: number) => a + b, 0))} tokens · 365 days
</span>
</div>
@@ -320,7 +320,7 @@ export function DailyTrendChart({ dailyTrend }) {
// ── Cost-aware Tooltip ─────────────────────────────────────────────────────
function CostTooltip({ active, payload, label }) {
function CostTooltip({ active, payload, label }: { active?: boolean; payload?: any[]; label?: any }) {
if (!active || !payload?.length) return null;
return (
<div className="rounded-lg border border-white/10 bg-surface px-3 py-2 text-xs shadow-lg">

View File

@@ -8,14 +8,14 @@ const MAX_BACKUPS_PER_TOOL = 5;
/**
* Get backup directory for a specific tool
*/
function getToolBackupDir(toolId) {
function getToolBackupDir(toolId: string) {
return path.join(BACKUP_DIR, toolId);
}
/**
* Ensure backup directory exists for a tool
*/
async function ensureBackupDir(toolId) {
async function ensureBackupDir(toolId: string) {
const dir = getToolBackupDir(toolId);
await fs.mkdir(dir, { recursive: true });
return dir;
@@ -24,7 +24,7 @@ async function ensureBackupDir(toolId) {
/**
* Generate a backup filename with timestamp
*/
function makeBackupName(originalPath) {
function makeBackupName(originalPath: string) {
const ext = path.extname(originalPath);
const base = path.basename(originalPath, ext);
const ts = new Date().toISOString().replace(/[:.]/g, "-");
@@ -35,7 +35,7 @@ function makeBackupName(originalPath) {
* Create a backup of a file before modifying it.
* Returns the backup path, or null if the source doesn't exist.
*/
export async function createBackup(toolId, filePath) {
export async function createBackup(toolId: string, filePath: string) {
try {
await fs.access(filePath);
} catch {
@@ -71,8 +71,8 @@ export async function createBackup(toolId, filePath) {
* Create backups for multiple files in one operation (e.g. Codex config.toml + auth.json).
* Returns an array of backup paths.
*/
export async function createMultiBackup(toolId, filePaths) {
const results = [];
export async function createMultiBackup(toolId: string, filePaths: string[]) {
const results: (string | null)[] = [];
for (const filePath of filePaths) {
const result = await createBackup(toolId, filePath);
results.push(result);
@@ -83,7 +83,7 @@ export async function createMultiBackup(toolId, filePaths) {
/**
* List all backups for a tool (sorted newest first).
*/
export async function listBackups(toolId) {
export async function listBackups(toolId: string) {
const dir = getToolBackupDir(toolId);
let entries;
@@ -94,7 +94,7 @@ export async function listBackups(toolId) {
}
const metaFiles = entries.filter((e) => e.endsWith(".meta.json"));
const backups = [];
const backups: any[] = [];
for (const metaFile of metaFiles) {
try {
@@ -127,14 +127,14 @@ export async function listBackups(toolId) {
}
// Sort newest first
backups.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
backups.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
return backups;
}
/**
* Restore a backup by its id (filename).
*/
export async function restoreBackup(toolId, backupId) {
export async function restoreBackup(toolId: string, backupId: string) {
const dir = getToolBackupDir(toolId);
const backupPath = path.join(dir, backupId);
const metaPath = backupPath + ".meta.json";
@@ -173,7 +173,7 @@ export async function restoreBackup(toolId, backupId) {
/**
* Delete a specific backup by its id.
*/
export async function deleteBackup(toolId, backupId) {
export async function deleteBackup(toolId: string, backupId: string) {
const dir = getToolBackupDir(toolId);
const backupPath = path.join(dir, backupId);
const metaPath = backupPath + ".meta.json";
@@ -196,18 +196,18 @@ export async function deleteBackup(toolId, backupId) {
* Enforce max backups per tool — removes oldest when limit exceeded.
* Groups by original file basename so each config file gets its own rotation.
*/
async function rotateBackups(toolId) {
async function rotateBackups(toolId: string) {
const all = await listBackups(toolId);
// Group by original file basename
const groups = {};
const groups: Record<string, any[]> = {};
for (const b of all) {
const key = path.basename(b.originalPath);
if (!groups[key]) groups[key] = [];
groups[key].push(b);
}
for (const [, group] of Object.entries(groups)) {
for (const [, group] of Object.entries(groups) as [string, any[]][]) {
// Already sorted newest first
if (group.length > MAX_BACKUPS_PER_TOOL) {
const toDelete = group.slice(MAX_BACKUPS_PER_TOOL);

View File

@@ -42,7 +42,7 @@ import { logAuditEvent } from "../../lib/compliance/index";
* Supports: OpenAI, Claude, Gemini, OpenAI Responses API formats
* Format detection and translation handled by translator
*/
export async function handleChat(request, clientRawRequest = null) {
export async function handleChat(request: any, clientRawRequest: any = null) {
// Pipeline: Start request telemetry
const reqId = generateRequestId();
const telemetry = new RequestTelemetry(reqId);
@@ -155,7 +155,7 @@ export async function handleChat(request, clientRawRequest = null) {
// Pre-check function: skip models where all accounts are in cooldown
// Uses modelAvailability module for TTL-based cooldowns
const checkModelAvailable = async (modelString) => {
const checkModelAvailable = async (modelString: string) => {
const parsed = parseModel(modelString);
const provider = parsed.provider;
if (!provider) return true; // can't determine provider, let it try
@@ -178,10 +178,10 @@ export async function handleChat(request, clientRawRequest = null) {
]);
telemetry.endPhase();
const response = await handleComboChat({
const response = await (handleComboChat as any)({
body,
combo,
handleSingleModel: (b, m) =>
handleSingleModel: (b: any, m: string) =>
handleSingleModelChat(b, m, clientRawRequest, request, combo.name, apiKeyInfo, telemetry),
isModelAvailable: checkModelAvailable,
log,
@@ -217,24 +217,24 @@ export async function handleChat(request, clientRawRequest = null) {
* credential retry loop.
*/
async function handleSingleModelChat(
body,
modelStr,
clientRawRequest = null,
request = null,
comboName = null,
apiKeyInfo = null,
telemetry = null
body: any,
modelStr: string,
clientRawRequest: any = null,
request: any = null,
comboName: string | null = null,
apiKeyInfo: any = null,
telemetry: any = null
) {
// 1. Resolve model → provider/model (or return error)
const modelInfo = await getModelInfo(modelStr);
if (!modelInfo.provider) {
if (modelInfo.errorType === "ambiguous_model") {
if ((modelInfo as any).errorType === "ambiguous_model") {
const message =
modelInfo.errorMessage ||
(modelInfo as any).errorMessage ||
`Ambiguous model '${modelStr}'. Use provider/model prefix (ex: gh/${modelStr} or cc/${modelStr}).`;
log.warn("CHAT", message, {
model: modelStr,
candidates: modelInfo.candidateAliases || modelInfo.candidateProviders || [],
candidates: (modelInfo as any).candidateAliases || (modelInfo as any).candidateProviders || [],
});
return errorResponse(HTTP_STATUS.BAD_REQUEST, message);
}
@@ -256,7 +256,7 @@ async function handleSingleModelChat(
// Pipeline: Check model availability (TTL cooldown)
if (!isModelAvailable(provider, model)) {
log.warn("AVAILABILITY", `${provider}/${model} is in cooldown, rejecting request`);
return unavailableResponse(
return (unavailableResponse as any)(
HTTP_STATUS.SERVICE_UNAVAILABLE,
`Model ${provider}/${model} is temporarily unavailable (cooldown)`,
30
@@ -267,11 +267,11 @@ async function handleSingleModelChat(
const breaker = getCircuitBreaker(provider, {
failureThreshold: 5,
resetTimeout: 30000,
onStateChange: (name, from, to) => log.info("CIRCUIT", `${name}: ${from}${to}`),
onStateChange: (name: string, from: string, to: string) => log.info("CIRCUIT", `${name}: ${from}${to}`),
});
if (!breaker.canExecute()) {
log.warn("CIRCUIT", `Circuit breaker OPEN for ${provider}, rejecting request`);
return unavailableResponse(
return (unavailableResponse as any)(
HTTP_STATUS.SERVICE_UNAVAILABLE,
`Provider ${provider} circuit breaker is open`,
30
@@ -314,7 +314,7 @@ async function handleSingleModelChat(
try {
const chatFn = () =>
runWithProxyContext(proxyInfo?.proxy || null, () =>
handleChatCore({
(handleChatCore as any)({
body: { ...body, model: `${provider}/${model}` },
modelInfo: { provider, model },
credentials: refreshedCredentials,
@@ -324,7 +324,7 @@ async function handleSingleModelChat(
apiKeyInfo,
userAgent,
comboName,
onCredentialsRefreshed: async (newCreds) => {
onCredentialsRefreshed: async (newCreds: any) => {
await updateProviderCredentials(credentials.connectionId, {
accessToken: newCreds.accessToken,
refreshToken: newCreds.refreshToken,
@@ -351,7 +351,7 @@ async function handleSingleModelChat(
} catch (cbErr) {
if (cbErr instanceof CircuitBreakerOpenError) {
log.warn("CIRCUIT", `${provider} circuit open during retry: ${cbErr.message}`);
return unavailableResponse(
return (unavailableResponse as any)(
HTTP_STATUS.SERVICE_UNAVAILABLE,
`Provider ${provider} circuit breaker is open`,
Math.ceil(cbErr.retryAfterMs / 1000)
@@ -425,12 +425,12 @@ async function handleSingleModelChat(
// ──── Extracted helpers (T-28) ────
function handleNoCredentials(
credentials,
excludeConnectionId,
provider,
model,
lastError,
lastStatus
credentials: any,
excludeConnectionId: string | null,
provider: string,
model: string,
lastError: string | null,
lastStatus: number | null
) {
if (credentials?.allRateLimited) {
const errorMsg = lastError || credentials.lastError || "Unavailable";
@@ -455,10 +455,10 @@ function handleNoCredentials(
);
}
async function safeResolveProxy(connectionId) {
async function safeResolveProxy(connectionId: string) {
try {
return await resolveProxyForConnection(connectionId);
} catch (proxyErr) {
} catch (proxyErr: any) {
log.debug("PROXY", `Failed to resolve proxy: ${proxyErr.message}`);
return null;
}

View File

@@ -19,7 +19,7 @@ import {
} from "@omniroute/open-sse/config/providerModels.js";
import { logProxyEvent } from "../../lib/proxyLogger";
import { logTranslationEvent } from "../../lib/translatorEvents";
import { updateProviderCredentials } from "../services/auth";
// updateProviderCredentials is dynamically imported from ../services/auth when needed
const HTTP_STATUS = {
BAD_REQUEST: 400,
@@ -34,17 +34,17 @@ const HTTP_STATUS = {
* @param {Function} errorResponse - Error response factory
* @returns {Promise<{ error?: Response, provider: string, model: string, sourceFormat: string, targetFormat: string }>}
*/
export async function resolveModelOrError(modelStr, body, log, errorResponse) {
export async function resolveModelOrError(modelStr: string, body: any, log: any, errorResponse: Function) {
const modelInfo = await getModelInfo(modelStr);
if (!modelInfo.provider) {
if (modelInfo.errorType === "ambiguous_model") {
if ((modelInfo as any).errorType === "ambiguous_model") {
const message =
modelInfo.errorMessage ||
(modelInfo as any).errorMessage ||
`Ambiguous model '${modelStr}'. Use provider/model prefix (ex: gh/${modelStr} or cc/${modelStr}).`;
log.warn("CHAT", message, {
model: modelStr,
candidates: modelInfo.candidateAliases || modelInfo.candidateProviders || [],
candidates: (modelInfo as any).candidateAliases || (modelInfo as any).candidateProviders || [],
});
return { error: errorResponse(HTTP_STATUS.BAD_REQUEST, message) };
}
@@ -155,7 +155,8 @@ export function buildChatCoreParams({
apiKeyInfo,
userAgent,
comboName,
onCredentialsRefreshed: async (newCreds) => {
onCredentialsRefreshed: async (newCreds: any) => {
const { updateProviderCredentials } = await import("../services/tokenRefresh");
await updateProviderCredentials(credentials.connectionId, {
accessToken: newCreds.accessToken,
refreshToken: newCreds.refreshToken,

View File

@@ -19,42 +19,41 @@ import {
export const TOKEN_EXPIRY_BUFFER_MS = BUFFER_MS;
// Wrap functions with local logger
export const refreshAccessToken = (provider, refreshToken, credentials) =>
export const refreshAccessToken = (provider: string, refreshToken: string, credentials: any) =>
_refreshAccessToken(provider, refreshToken, credentials, log);
export const refreshClaudeOAuthToken = (refreshToken) =>
export const refreshClaudeOAuthToken = (refreshToken: string) =>
_refreshClaudeOAuthToken(refreshToken, log);
export const refreshGoogleToken = (refreshToken, clientId, clientSecret) =>
export const refreshGoogleToken = (refreshToken: string, clientId: string, clientSecret: string) =>
_refreshGoogleToken(refreshToken, clientId, clientSecret, log);
export const refreshQwenToken = (refreshToken) => _refreshQwenToken(refreshToken, log);
export const refreshQwenToken = (refreshToken: string) => _refreshQwenToken(refreshToken, log);
export const refreshCodexToken = (refreshToken) => _refreshCodexToken(refreshToken, log);
export const refreshCodexToken = (refreshToken: string) => _refreshCodexToken(refreshToken, log);
export const refreshIflowToken = (refreshToken) => _refreshIflowToken(refreshToken, log);
export const refreshIflowToken = (refreshToken: string) => _refreshIflowToken(refreshToken, log);
export const refreshGitHubToken = (refreshToken) => _refreshGitHubToken(refreshToken, log);
export const refreshGitHubToken = (refreshToken: string) => _refreshGitHubToken(refreshToken, log);
export const refreshCopilotToken = (githubAccessToken) =>
export const refreshCopilotToken = (githubAccessToken: string) =>
_refreshCopilotToken(githubAccessToken, log);
export const getAccessToken = (provider, credentials) =>
export const getAccessToken = (provider: string, credentials: any) =>
_getAccessToken(provider, credentials, log);
export const refreshTokenByProvider = (provider, credentials) =>
export const refreshTokenByProvider = (provider: string, credentials: any) =>
_refreshTokenByProvider(provider, credentials, log);
export const formatProviderCredentials = (provider, credentials) =>
export const formatProviderCredentials = (provider: string, credentials: any) =>
_formatProviderCredentials(provider, credentials, log);
export const getAllAccessTokens = (userInfo) => _getAllAccessTokens(userInfo, log);
export const getAllAccessTokens = (userInfo: any) => _getAllAccessTokens(userInfo, log);
// Local-specific: Update credentials in localDb
export async function updateProviderCredentials(connectionId, newCredentials) {
export async function updateProviderCredentials(connectionId: string, newCredentials: any) {
try {
const updates = {};
const updates: Record<string, any> = {};
if (newCredentials.accessToken) {
updates.accessToken = newCredentials.accessToken;
@@ -79,14 +78,14 @@ export async function updateProviderCredentials(connectionId, newCredentials) {
} catch (error) {
log.error("TOKEN_REFRESH", "Error updating credentials in localDb", {
connectionId,
error: error.message,
error: (error as any).message,
});
return false;
}
}
// Local-specific: Check and refresh token proactively
export async function checkAndRefreshToken(provider, credentials) {
export async function checkAndRefreshToken(provider: string, credentials: any) {
let updatedCredentials = { ...credentials };
// Check regular token expiry
@@ -150,7 +149,7 @@ export async function checkAndRefreshToken(provider, credentials) {
}
// Local-specific: Refresh GitHub and Copilot tokens together
export async function refreshGitHubAndCopilotTokens(credentials) {
export async function refreshGitHubAndCopilotTokens(credentials: any) {
const newGitHubCredentials = await refreshGitHubToken(credentials.refreshToken);
if (newGitHubCredentials?.accessToken) {
const copilotToken = await refreshCopilotToken(newGitHubCredentials.accessToken);