Skip to main content
Glama
provider-factory.ts6.13 kB
/** * Provider Factory * * Factory for creating VCS provider instances dynamically. * Supports GitHub, Gitea, and multi-provider configurations. */ import { BaseProvider, MultiProvider } from './base-provider.js'; import { ProviderConfig, ProviderResult } from './types.js'; import { configManager } from '../config.js'; export type ProviderType = 'github' | 'gitea'; export class ProviderFactory { private config: ProviderConfig; constructor(config: ProviderConfig) { this.config = config; } /** * Create a single provider instance */ createProvider(type: ProviderType): BaseProvider { switch (type) { case 'github': return this.createGitHubProvider(); case 'gitea': return this.createGiteaProvider(); default: throw new Error(`Unsupported provider type: ${type}`); } } /** * Create a multi-provider instance that handles multiple providers */ createMultiProvider(types: ProviderType[]): MultiProvider { const providers = types.map(type => this.createProvider(type)); return new MultiProviderImpl(providers); } /** * Create provider based on string identifier */ createProviderFromString(provider: string): BaseProvider | MultiProvider { // UNIVERSAL MODE: Auto-aplicar 'both' se modo universal ativo e provider não especificado if (!provider && configManager.isUniversalMode()) { provider = 'both'; } switch (provider) { case 'github': return this.createProvider('github'); case 'gitea': return this.createProvider('gitea'); case 'both': return this.createMultiProvider(['github', 'gitea']); default: // UNIVERSAL MODE: Default para 'both' no modo universal if (configManager.isUniversalMode()) { return this.createMultiProvider(['github', 'gitea']); } throw new Error(`Invalid provider: ${provider}. Valid options: github, gitea, both`); } } /** * Get available providers based on configuration */ getAvailableProviders(): ProviderType[] { const available: ProviderType[] = []; if (this.config.github?.token && this.config.github?.username) { available.push('github'); } if (this.config.gitea?.url && this.config.gitea?.token && this.config.gitea?.username) { available.push('gitea'); } return available; } /** * Check if a provider type is available */ isProviderAvailable(type: ProviderType): boolean { return this.getAvailableProviders().includes(type); } /** * Validate provider configuration */ validateProviderConfig(type: ProviderType): { valid: boolean; missingFields: string[]; } { switch (type) { case 'github': return this.validateGitHubConfig(); case 'gitea': return this.validateGiteaConfig(); default: return { valid: false, missingFields: ['Invalid provider type'] }; } } private createGitHubProvider(): BaseProvider { if (!this.config.github) { throw new Error('GitHub configuration is missing'); } // Import GitHubProvider dynamically to avoid circular dependencies const { GitHubProvider } = require('./github-provider.js'); return new GitHubProvider(this.config.github); } private createGiteaProvider(): BaseProvider { if (!this.config.gitea) { throw new Error('Gitea configuration is missing'); } // Import GiteaProvider dynamically to avoid circular dependencies const { GiteaProvider } = require('./gitea-provider.js'); return new GiteaProvider(this.config.gitea); } private validateGitHubConfig(): { valid: boolean; missingFields: string[] } { const missing: string[] = []; if (!this.config.github?.token) { missing.push('GITHUB_TOKEN'); } if (!this.config.github?.username) { missing.push('GITHUB_USERNAME'); } return { valid: missing.length === 0, missingFields: missing }; } private validateGiteaConfig(): { valid: boolean; missingFields: string[] } { const missing: string[] = []; if (!this.config.gitea?.url) { missing.push('GITEA_URL'); } if (!this.config.gitea?.token) { missing.push('GITEA_TOKEN'); } if (!this.config.gitea?.username) { missing.push('GITEA_USERNAME'); } return { valid: missing.length === 0, missingFields: missing }; } /** * Get default provider based on mode */ getDefaultProvider(): string { return configManager.isUniversalMode() ? 'both' : 'github'; } } /** * Multi-provider implementation */ class MultiProviderImpl implements MultiProvider { providers: BaseProvider[]; constructor(providers: BaseProvider[]) { this.providers = providers; } /** * Execute operation on all configured providers in parallel */ async executeOperation(operation: string, params: any): Promise<ProviderResult[]> { const configuredProviders = this.getConfiguredProviders(); if (configuredProviders.length === 0) { throw new Error('No providers are configured'); } // Execute operations in parallel const promises = configuredProviders.map(async (provider) => { try { return await provider.executeOperation(operation, params); } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; return { success: false, error: { code: 'PROVIDER_ERROR', message: `Provider ${provider.getName()} failed: ${errorMessage}`, details: error }, provider: provider.getName() }; } }); return Promise.all(promises); } /** * Get only the configured providers */ getConfiguredProviders(): BaseProvider[] { return this.providers.filter(provider => provider.isConfigured()); } /** * Check if any provider is configured */ isAnyProviderConfigured(): boolean { return this.getConfiguredProviders().length > 0; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Andre-Buzeli/git-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server