115 lines
3.9 KiB
TypeScript
115 lines
3.9 KiB
TypeScript
import * as plugins from '../plugins.ts';
|
|
import { logger } from '../logging.ts';
|
|
import type * as interfaces from '../../ts_interfaces/index.ts';
|
|
import { BaseProvider, GiteaProvider, GitLabProvider } from '../providers/index.ts';
|
|
|
|
const CONNECTIONS_FILE = './.nogit/connections.json';
|
|
|
|
/**
|
|
* Manages provider connections - persists to .nogit/connections.json
|
|
* and creates provider instances on demand.
|
|
*/
|
|
export class ConnectionManager {
|
|
private connections: interfaces.data.IProviderConnection[] = [];
|
|
|
|
async init(): Promise<void> {
|
|
await this.loadConnections();
|
|
}
|
|
|
|
private async loadConnections(): Promise<void> {
|
|
try {
|
|
const text = await Deno.readTextFile(CONNECTIONS_FILE);
|
|
this.connections = JSON.parse(text);
|
|
logger.info(`Loaded ${this.connections.length} connection(s)`);
|
|
} catch {
|
|
this.connections = [];
|
|
logger.debug('No existing connections file found, starting fresh');
|
|
}
|
|
}
|
|
|
|
private async saveConnections(): Promise<void> {
|
|
// Ensure .nogit directory exists
|
|
try {
|
|
await Deno.mkdir('./.nogit', { recursive: true });
|
|
} catch { /* already exists */ }
|
|
await Deno.writeTextFile(CONNECTIONS_FILE, JSON.stringify(this.connections, null, 2));
|
|
}
|
|
|
|
getConnections(): interfaces.data.IProviderConnection[] {
|
|
// Return connections without exposing tokens
|
|
return this.connections.map((c) => ({ ...c, token: '***' }));
|
|
}
|
|
|
|
getConnection(id: string): interfaces.data.IProviderConnection | undefined {
|
|
return this.connections.find((c) => c.id === id);
|
|
}
|
|
|
|
async createConnection(
|
|
name: string,
|
|
providerType: interfaces.data.TProviderType,
|
|
baseUrl: string,
|
|
token: string,
|
|
): Promise<interfaces.data.IProviderConnection> {
|
|
const connection: interfaces.data.IProviderConnection = {
|
|
id: crypto.randomUUID(),
|
|
name,
|
|
providerType,
|
|
baseUrl: baseUrl.replace(/\/+$/, ''),
|
|
token,
|
|
createdAt: Date.now(),
|
|
status: 'disconnected',
|
|
};
|
|
this.connections.push(connection);
|
|
await this.saveConnections();
|
|
logger.success(`Connection created: ${name} (${providerType})`);
|
|
return { ...connection, token: '***' };
|
|
}
|
|
|
|
async updateConnection(
|
|
id: string,
|
|
updates: { name?: string; baseUrl?: string; token?: string },
|
|
): Promise<interfaces.data.IProviderConnection> {
|
|
const conn = this.connections.find((c) => c.id === id);
|
|
if (!conn) throw new Error(`Connection not found: ${id}`);
|
|
if (updates.name) conn.name = updates.name;
|
|
if (updates.baseUrl) conn.baseUrl = updates.baseUrl.replace(/\/+$/, '');
|
|
if (updates.token) conn.token = updates.token;
|
|
await this.saveConnections();
|
|
return { ...conn, token: '***' };
|
|
}
|
|
|
|
async deleteConnection(id: string): Promise<void> {
|
|
const idx = this.connections.findIndex((c) => c.id === id);
|
|
if (idx === -1) throw new Error(`Connection not found: ${id}`);
|
|
this.connections.splice(idx, 1);
|
|
await this.saveConnections();
|
|
logger.info(`Connection deleted: ${id}`);
|
|
}
|
|
|
|
async testConnection(id: string): Promise<{ ok: boolean; error?: string }> {
|
|
const provider = this.getProvider(id);
|
|
const result = await provider.testConnection();
|
|
const conn = this.connections.find((c) => c.id === id)!;
|
|
conn.status = result.ok ? 'connected' : 'error';
|
|
await this.saveConnections();
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Factory: returns the correct provider instance for a connection ID
|
|
*/
|
|
getProvider(connectionId: string): BaseProvider {
|
|
const conn = this.connections.find((c) => c.id === connectionId);
|
|
if (!conn) throw new Error(`Connection not found: ${connectionId}`);
|
|
|
|
switch (conn.providerType) {
|
|
case 'gitea':
|
|
return new GiteaProvider(conn.id, conn.baseUrl, conn.token);
|
|
case 'gitlab':
|
|
return new GitLabProvider(conn.id, conn.baseUrl, conn.token);
|
|
default:
|
|
throw new Error(`Unknown provider type: ${conn.providerType}`);
|
|
}
|
|
}
|
|
}
|